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-763-g8905bb4


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-763-g8905bb4
Date: Sun, 9 Oct 2016 06:17:45 +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=8905bb4805cf4ebcff9ba3d99073b81c906399f6

The branch, master has been updated
       via  8905bb4805cf4ebcff9ba3d99073b81c906399f6 (commit)
       via  aac8beae014b6345bc3682c6d0f5b544b2a84956 (commit)
       via  87ef8884693eb0cdcdafa2365c86709f33e3a375 (commit)
       via  8b8f29eb6485e5ab09e2215d595fbbf45c27c97b (commit)
      from  296d0bc958142cafe0e839cd43236c14c8310ee2 (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 8905bb4805cf4ebcff9ba3d99073b81c906399f6
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Oct 8 23:36:50 2016 +0300

    Fix mu_parseopt. Add testsuite for it.
    
    * include/mailutils/opt.h (mu_parseopt) <po_permuted>: New member.
    * libmailutils/opt/help.c (print_option): Fix display of optional
    arguments.
    * libmailutils/opt/opt.c (next_opt,parse): Fix start-of-arguments
    index.
    Move permutation into a separate function.
    * libmailutils/opt/progname.c (mu_set_progname): Remove eventual lt-
    prefix.
    * libmailutils/tests/Makefile.am: Add new tests.
    * libmailutils/tests/parseopt.c: Use environment to control
    mu_parseopt flags.
    * libmailutils/tests/testsuite.at: Add new tests.
    * libmailutils/tests/strtoc.at: Update.
    
    * libmailutils/tests/parseopt00.at: New file.
    * libmailutils/tests/parseopt01.at: New file.
    * libmailutils/tests/parseopt02.at: New file.
    * libmailutils/tests/parseopt03.at: New file.
    * libmailutils/tests/parseopt04.at: New file.
    * libmailutils/tests/parseopt05.at: New file.
    * libmailutils/tests/parseopt06.at: New file.
    * libmailutils/tests/parseopt07.at: New file.
    * libmailutils/tests/parseopt08.at: New file.
    * libmailutils/tests/parseopt09.at: New file.
    * libmailutils/tests/parseopt10.at: New file.
    * libmailutils/tests/parseopt11.at: New file.
    * libmailutils/tests/parseopt12.at: New file.
    * libmailutils/tests/parseopt13.at: New file.
    * libmailutils/tests/parseopt14.at: New file.
    * libmailutils/tests/parseopt15.at: New file.
    * libmailutils/tests/parseopt16.at: New file.
    * libmailutils/tests/parseopt17.at: New file.
    * libmailutils/tests/parseopt18.at: New file.
    * libmailutils/tests/parseopt19.at: New file.
    * libmailutils/tests/parseopt20.at: New file.
    * libmailutils/tests/parseopt21.at: New file.
    * libmailutils/tests/parseopt22.at: New file.

commit aac8beae014b6345bc3682c6d0f5b544b2a84956
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Oct 8 16:21:23 2016 +0300

    Use mu_c_type_t throughout the code.  Get rid of mu_cfg_param_data_type.
    
    * include/mailutils/cfg.h (mu_cfg_param_data_type): Remove.
    (mu_cfg_param_type): New enum.
    (mu_cfg_param) <type>: Change type to int.
    (mu_cfg_cidr): Remove.
    (mu_cfg_parse_boolean): Remove.  All uses updated.
    * include/mailutils/util.h (mu_c_void): New constant.
    (mu_c_type_str): New extern/
    * libmailutils/string/str_to_c.c (mu_c_type_str): New global.
    * libmailutils/cfg/format.c (mu_cfg_data_type_string): Rename
    to mu_c_type_string; change argument type.
    All uses updated.
    * libmailutils/cfg/parser.y: Use mu_str_to_c for value
    conversion.
    
    * libmailutils/tests/.gitignore: Update.
    * libmailutils/tests/Makefile.am: Add strtoc.at; build strtoc
    * libmailutils/tests/strtoc.at: New file.
    * libmailutils/tests/strtoc.c: New file.
    * libmailutils/tests/testsuite.at: Include strtoc.at
    
    * comsat/comsat.c: Use mu_c_type_t types.
    * dotlock/dotlock.c: Likewise.
    * imap4d/imap4d.c: Likewise.
    * lib/manlock.c: Likewise.
    * lib/tcpwrap.c: Likewise.
    * libmailutils/server/msrv.c: Likewise.
    * libmu_argp/muinit.c: Likewise.
    * libmu_cfg/common.c: Likewise.
    * libmu_cfg/gsasl.c: Likewise.
    * libmu_cfg/ldap.c: Likewise.
    * libmu_cfg/pam.c: Likewise.
    * libmu_cfg/radius.c: Likewise.
    * libmu_cfg/sieve.c: Likewise.
    * libmu_cfg/sql.c: Likewise.
    * libmu_cfg/tls.c: Likewise.
    * libmu_cfg/virtdomain.c: Likewise.
    * maidag/maidag.c: Likewise.
    * mimeview/mimeview.c: Likewise.
    * movemail/movemail.c: Likewise.
    * pop3d/pop3d.c: Likewise.
    * readmsg/readmsg.c: Likewise.
    * sieve/sieve.c: Likewise.

commit 87ef8884693eb0cdcdafa2365c86709f33e3a375
Author: Sergey Poznyakoff <address@hidden>
Date:   Fri Oct 7 21:58:50 2016 +0300

    Add generic library for option parsing.
    
    * configure.ac: Build libmailutils/opt
    * include/mailutils/Makefile.am: Add opt.h
    * include/mailutils/opt.h: New file.
    * include/mailutils/util.h (mu_c_type_t): New datatype.
    (mu_str_to_c): New proto.
    * libmailutils/Makefile.am: Add opt to subdirs.
    
    * libmailutils/opt/Makefile.am: New file.
    * libmailutils/opt/help.c: New file.
    * libmailutils/opt/opt.c: New file.
    * libmailutils/opt/progname.c: New file.
    
    * libmailutils/string/Makefile.am: Add new files.
    * libmailutils/string/str_to_c.c: New file.
    * libmailutils/string/to_sn.c: New file.
    * libmailutils/string/to_un.c: New file.
    
    * libmailutils/tests/.gitignore: Update.
    * libmailutils/tests/Makefile.am: Update.
    * libmailutils/tests/parseopt.c: New file.

commit 8b8f29eb6485e5ab09e2215d595fbbf45c27c97b
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Oct 6 09:25:43 2016 +0300

    Bugfixes
    
    * mh/rmf.c (current_folder_path): Treat name as folder while expanding.
    * mail/unset.c (mail_unset): Fix the behavior when no arguments were
    given.

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

Summary of changes:
 comsat/comsat.c                                    |   16 +-
 configure.ac                                       |    1 +
 dotlock/dotlock.c                                  |    6 +-
 imap4d/imap4d.c                                    |   32 +-
 include/mailutils/Makefile.am                      |    1 +
 include/mailutils/cfg.h                            |   40 +-
 include/mailutils/opt.h                            |  169 ++++++
 include/mailutils/util.h                           |   31 +-
 lib/manlock.c                                      |    4 +-
 lib/tcpwrap.c                                      |    8 +-
 libmailutils/Makefile.am                           |    3 +-
 libmailutils/cfg/format.c                          |   41 +-
 libmailutils/cfg/parser.y                          |  388 +-----------
 libmailutils/{mailer => opt}/Makefile.am           |   14 +-
 libmailutils/opt/help.c                            |  345 +++++++++++
 libmailutils/opt/opt.c                             |  638 ++++++++++++++++++++
 .../virtdomain.c => libmailutils/opt/progname.c    |   39 +-
 libmailutils/server/msrv.c                         |   14 +-
 libmailutils/string/Makefile.am                    |    5 +-
 libmailutils/string/str_to_c.c                     |  295 +++++++++
 libmailutils/string/to_sn.c                        |   37 ++
 libmailutils/string/to_un.c                        |   34 ++
 libmailutils/tests/.gitignore                      |    2 +
 libmailutils/tests/Makefile.am                     |   26 +
 libmailutils/tests/parseopt.c                      |  118 ++++
 libmailutils/tests/{strout.at => parseopt00.at}    |   30 +-
 libmailutils/tests/{strerr.at => parseopt01.at}    |   34 +-
 libmailutils/tests/{strerr.at => parseopt02.at}    |   34 +-
 .../tests/parseopt03.at                            |   35 +-
 .../tests/parseopt04.at                            |   35 +-
 .../tests/parseopt05.at                            |   35 +-
 .../tests/parseopt06.at                            |   35 +-
 .../tests/parseopt07.at                            |   35 +-
 libmailutils/tests/{strerr.at => parseopt08.at}    |   34 +-
 .../tests/parseopt09.at                            |   35 +-
 .../tests/parseopt10.at                            |   35 +-
 .../tests/parseopt11.at                            |   35 +-
 .../tests/parseopt12.at                            |   35 +-
 .../tests/parseopt13.at                            |   35 +-
 libmailutils/tests/{strerr.at => parseopt14.at}    |   26 +-
 .../tests/parseopt15.at                            |   35 +-
 libmailutils/tests/{strerr.at => parseopt16.at}    |   30 +-
 .../tests/parseopt17.at                            |   35 +-
 libmailutils/tests/{strerr.at => parseopt18.at}    |   32 +-
 .../tests/parseopt19.at                            |   34 +-
 libmailutils/tests/{strout.at => parseopt20.at}    |   26 +-
 .../tests/parseopt21.at                            |   19 +-
 libmailutils/tests/{strout.at => parseopt22.at}    |   26 +-
 .../version.at => libmailutils/tests/strtoc.at     |    8 +-
 libmailutils/tests/strtoc.c                        |  354 +++++++++++
 libmailutils/tests/testsuite.at                    |   28 +
 libmu_argp/muinit.c                                |    2 +-
 libmu_cfg/common.c                                 |   32 +-
 libmu_cfg/gsasl.c                                  |   12 +-
 libmu_cfg/ldap.c                                   |   18 +-
 libmu_cfg/pam.c                                    |    2 +-
 libmu_cfg/radius.c                                 |    8 +-
 libmu_cfg/sieve.c                                  |    4 +-
 libmu_cfg/sql.c                                    |   20 +-
 libmu_cfg/tls.c                                    |   10 +-
 libmu_cfg/virtdomain.c                             |    2 +-
 maidag/maidag.c                                    |   18 +-
 mail/unset.c                                       |    2 +-
 mh/rmf.c                                           |    4 +-
 mimeview/mimeview.c                                |    4 +-
 movemail/movemail.c                                |   16 +-
 pop3d/pop3d.c                                      |   20 +-
 readmsg/readmsg.c                                  |   14 +-
 sieve/sieve.c                                      |   10 +-
 69 files changed, 2664 insertions(+), 976 deletions(-)
 create mode 100644 include/mailutils/opt.h
 copy libmailutils/{mailer => opt}/Makefile.am (77%)
 create mode 100644 libmailutils/opt/help.c
 create mode 100644 libmailutils/opt/opt.c
 copy libmu_cfg/virtdomain.c => libmailutils/opt/progname.c (57%)
 create mode 100644 libmailutils/string/str_to_c.c
 create mode 100644 libmailutils/string/to_sn.c
 create mode 100644 libmailutils/string/to_un.c
 create mode 100644 libmailutils/tests/parseopt.c
 copy libmailutils/tests/{strout.at => parseopt00.at} (73%)
 copy libmailutils/tests/{strerr.at => parseopt01.at} (68%)
 copy libmailutils/tests/{strerr.at => parseopt02.at} (68%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt03.at (66%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt04.at (65%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt05.at (65%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt06.at (66%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt07.at (66%)
 copy libmailutils/tests/{strerr.at => parseopt08.at} (68%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt09.at (66%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt10.at (65%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt11.at (65%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt12.at (66%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt13.at (66%)
 copy libmailutils/tests/{strerr.at => parseopt14.at} (68%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt15.at (64%)
 copy libmailutils/tests/{strerr.at => parseopt16.at} (72%)
 copy imap4d/tests/create01.at => libmailutils/tests/parseopt17.at (67%)
 copy libmailutils/tests/{strerr.at => parseopt18.at} (67%)
 copy imap4d/tests/create02.at => libmailutils/tests/parseopt19.at (65%)
 copy libmailutils/tests/{strout.at => parseopt20.at} (73%)
 copy testsuite/lstuid00.at => libmailutils/tests/parseopt21.at (73%)
 copy libmailutils/tests/{strout.at => parseopt22.at} (75%)
 copy mail/tests/version.at => libmailutils/tests/strtoc.at (85%)
 create mode 100644 libmailutils/tests/strtoc.c

diff --git a/comsat/comsat.c b/comsat/comsat.c
index 48add9a..0911a37 100644
--- a/comsat/comsat.c
+++ b/comsat/comsat.c
@@ -128,7 +128,7 @@ biffrc_error_ctl (mu_config_value_t *val, int flag)
   
   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
     return 1;
-  if (mu_cfg_parse_boolean (val->v.string, &res))
+  if (mu_str_to_c (val->v.string, mu_c_bool, &res, NULL))
     mu_diag_output (MU_LOG_ERROR, _("not a boolean"));
   else if (res)
     biffrc_errors |= flag;
@@ -150,9 +150,9 @@ cb_biffrc_errors_to_err (void *data, mu_config_value_t *val)
 }
 
 struct mu_cfg_param comsat_cfg_param[] = {
-  { "allow-biffrc", mu_cfg_bool, &allow_biffrc, 0, NULL,
+  { "allow-biffrc", mu_c_bool, &allow_biffrc, 0, NULL,
     N_("Read .biffrc file from the user home directory.") },
-  { "require-tty", mu_cfg_bool, &require_tty, 0, NULL,
+  { "require-tty", mu_c_bool, &require_tty, 0, NULL,
     N_("Notify only if the user is logged on one of the ttys.") },
   { "biffrc-errors-to-tty", mu_cfg_callback, NULL, 0, cb_biffrc_errors_to_tty,
     N_("Send biffrc errors to user's tty."),
@@ -160,17 +160,17 @@ struct mu_cfg_param comsat_cfg_param[] = {
   { "biffrc-errors-to-err", mu_cfg_callback, NULL, 0, cb_biffrc_errors_to_err,
     N_("Send biffrc errors to Mailutils error output."),
     N_("arg: bool") },
-  { "max-lines", mu_cfg_int, &maxlines, 0, NULL,
+  { "max-lines", mu_c_int, &maxlines, 0, NULL,
     N_("Maximum number of message body lines to be output.") },
-  { "max-requests", mu_cfg_uint, &maxrequests, 0, NULL,
+  { "max-requests", mu_c_uint, &maxrequests, 0, NULL,
     N_("Maximum number of incoming requests per request control interval.") },
-  { "request-control-interval", mu_cfg_time, &request_control_interval,
+  { "request-control-interval", mu_c_time, &request_control_interval,
     0, NULL,
     N_("Set control interval.") },
-  { "overflow-control-interval", mu_cfg_time, &overflow_control_interval,
+  { "overflow-control-interval", mu_c_time, &overflow_control_interval,
     0, NULL,
     N_("Set overflow control interval.") },
-  { "overflow-delay-time", mu_cfg_time, &overflow_delay_time,
+  { "overflow-delay-time", mu_c_time, &overflow_delay_time,
     0, NULL,
     N_("Time to sleep after the first overflow occurs.") },
   { ".server", mu_cfg_section, NULL, 0, NULL,
diff --git a/configure.ac b/configure.ac
index d473f80..7bd3641 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1519,6 +1519,7 @@ AC_CONFIG_FILES([
  libmailutils/mailer/Makefile
  libmailutils/mime/Makefile
  libmailutils/msgset/Makefile
+ libmailutils/opt/Makefile
  libmailutils/property/Makefile
  libmailutils/server/Makefile
  libmailutils/string/Makefile
diff --git a/dotlock/dotlock.c b/dotlock/dotlock.c
index eaf5254..c6a96c5 100644
--- a/dotlock/dotlock.c
+++ b/dotlock/dotlock.c
@@ -122,11 +122,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
 
 struct mu_cfg_param dotlock_cfg_param[] = {
-  { "force", mu_cfg_time, &force, 0, NULL,
+  { "force", mu_c_time, &force, 0, NULL,
     N_("Forcibly break an existing lock older than the specified time.") },
-  { "retry", mu_cfg_int, &retries, 0, NULL,
+  { "retry", mu_c_int, &retries, 0, NULL,
     N_("Number of times to retry acquiring the lock.") },
-  { "debug", mu_cfg_bool, &debug, 0, NULL,
+  { "debug", mu_c_bool, &debug, 0, NULL,
     N_("Print details of failure reasons to stderr.") },
   { NULL }
 };
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index bf7c8c2..a256dd4 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -321,7 +321,7 @@ cb_tls_required (void *data, mu_config_value_t *val)
 
   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
     return 1;
-  if (mu_cfg_parse_boolean (val->v.string, &bv))
+  if (mu_str_to_c (val->v.string, mu_c_bool, &bv, NULL))
     mu_error (_("Not a boolean value"));
   else if (bv)
     {
@@ -384,28 +384,28 @@ static struct mu_cfg_param imap4d_srv_param[] = {
 };
 
 static struct mu_cfg_param imap4d_cfg_param[] = {
-  { "allow-users", MU_CFG_LIST_OF(mu_cfg_string), &auth_allow_user_list,
+  { "allow-users", MU_CFG_LIST_OF(mu_c_string), &auth_allow_user_list,
     0, NULL, 
     N_("Allow access to users from this list.") },
-  { "deny-users", MU_CFG_LIST_OF(mu_cfg_string), &auth_deny_user_list,
+  { "deny-users", MU_CFG_LIST_OF(mu_c_string), &auth_deny_user_list,
     0, NULL, 
     N_("Deny access to users from this list.") },
-  { "allow-groups", MU_CFG_LIST_OF(mu_cfg_string), &auth_allow_group_list,
+  { "allow-groups", MU_CFG_LIST_OF(mu_c_string), &auth_allow_group_list,
     0, NULL, 
     N_("Allow access if the user group is in this list.") },
-  { "deny-groups", MU_CFG_LIST_OF(mu_cfg_string), &auth_deny_group_list,
+  { "deny-groups", MU_CFG_LIST_OF(mu_c_string), &auth_deny_group_list,
     0, NULL, 
     N_("Deny access if the user group is in this list.") },
   
-  { "homedir", mu_cfg_string, &modify_homedir, 0, NULL,
+  { "homedir", mu_c_string, &modify_homedir, 0, NULL,
     N_("Modify home directory.") },
-  { "personal-namespace", MU_CFG_LIST_OF(mu_cfg_string), 
&namespace[NS_PRIVATE],
+  { "personal-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_PRIVATE],
     0, NULL, 
     N_("Set personal namespace.") },
-  { "other-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_OTHER],
+  { "other-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_OTHER],
     0, NULL, 
     N_("Set other users' namespace.") },
-  { "shared-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_SHARED],
+  { "shared-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_SHARED],
     0, NULL,
     N_("Set shared namespace.") },
   { "other-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_OTHER], 0,
@@ -414,9 +414,9 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
   { "shared-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_SHARED], 0,
     cb_mailbox_mode,
     N_("File mode for mailboxes in shared namespace.") },
-  { "login-disabled", mu_cfg_bool, &login_disabled, 0, NULL,
+  { "login-disabled", mu_c_bool, &login_disabled, 0, NULL,
     N_("Disable LOGIN command.") },
-  { "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL,
+  { "create-home-dir", mu_c_bool, &create_home_dir, 0, NULL,
     N_("If true, create non-existing user home directories.") },
   { "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode,
     N_("File mode for creating user home directories (octal)."),
@@ -437,19 +437,19 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
        "  ident[://:<port: string-or-number>]\n"
        "  stdio"),
     N_("mode") },
-  { "preauth-only", mu_cfg_bool, &preauth_only, 0, NULL,
+  { "preauth-only", mu_c_bool, &preauth_only, 0, NULL,
     N_("Use only preauth mode.  If unable to setup it, disconnect "
        "immediately.") },
-  { "ident-keyfile", mu_cfg_string, &ident_keyfile, 0, NULL,
+  { "ident-keyfile", mu_c_string, &ident_keyfile, 0, NULL,
     N_("Name of DES keyfile for decoding encrypted ident responses.") },
-  { "ident-encrypt-only", mu_cfg_bool, &ident_encrypt_only, 0, NULL,
+  { "ident-encrypt-only", mu_c_bool, &ident_encrypt_only, 0, NULL,
     N_("Use only encrypted ident responses.") },
-  { "id-fields", MU_CFG_LIST_OF(mu_cfg_string), &imap4d_id_list, 0, NULL,
+  { "id-fields", MU_CFG_LIST_OF(mu_c_string), &imap4d_id_list, 0, NULL,
     N_("List of fields to return in response to ID command.") },
   { "mandatory-locking", mu_cfg_section },
   { ".server", mu_cfg_section, NULL, 0, NULL,
     N_("Server configuration.") },
-  { "transcript", mu_cfg_bool, &imap4d_transcript, 0, NULL,
+  { "transcript", mu_c_bool, &imap4d_transcript, 0, NULL,
     N_("Set global transcript mode.") },
   TCP_WRAPPERS_CONFIG
   { NULL }
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index 361ebdc..ba87486 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -79,6 +79,7 @@ pkginclude_HEADERS = \
  nntp.h\
  observer.h\
  opool.h\
+ opt.h\
  pam.h\
  parse822.h\
  pop3.h\
diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h
index c6eaf2c..7ea8e08 100644
--- a/include/mailutils/cfg.h
+++ b/include/mailutils/cfg.h
@@ -22,6 +22,7 @@
 #include <mailutils/list.h>
 #include <mailutils/debug.h>
 #include <mailutils/opool.h>
+#include <mailutils/util.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -113,27 +114,6 @@ void mu_cfg_destroy_tree (mu_cfg_tree_t **tree);
 int mu_cfg_preorder (mu_list_t nodelist, struct mu_cfg_iter_closure *);
 
 
-/* Table-driven parsing */
-enum mu_cfg_param_data_type
-  {
-    mu_cfg_string,
-    mu_cfg_short,
-    mu_cfg_ushort,
-    mu_cfg_int,
-    mu_cfg_uint,
-    mu_cfg_long,
-    mu_cfg_ulong,
-    mu_cfg_size,
-    mu_cfg_off,
-    mu_cfg_time,
-    mu_cfg_bool,
-    mu_cfg_ipv4,
-    mu_cfg_cidr,
-    mu_cfg_host,
-    mu_cfg_callback,
-    mu_cfg_section
-  };
-
 #define MU_CFG_LIST_MASK 0x8000
 #define MU_CFG_LIST_OF(t) ((t) | MU_CFG_LIST_MASK)
 #define MU_CFG_TYPE(t) ((t) & ~MU_CFG_LIST_MASK)
@@ -141,10 +121,16 @@ enum mu_cfg_param_data_type
   
 typedef int (*mu_cfg_callback_t) (void *, mu_config_value_t *);
 
+enum mu_cfg_param_type
+  {
+    mu_cfg_section = mu_c_void + 1,
+    mu_cfg_callback
+  };
+  
 struct mu_cfg_param
 {
   const char *ident;
-  enum mu_cfg_param_data_type type;
+  int type;       /* One of enum mu_c_type or mu_cfg_param_type values */
   void *data;
   size_t offset;
   mu_cfg_callback_t callback;
@@ -197,14 +183,6 @@ struct mu_cfg_cont
   } v;
 };
 
-typedef struct mu_cfg_cidr mu_cfg_cidr_t;
-
-struct mu_cfg_cidr
-{
-  struct in_addr addr;
-  unsigned long mask;
-};
-
 #define MU_CFG_PATH_DELIM '.'
 #define MU_CFG_PATH_DELIM_STR "."
   
@@ -271,8 +249,6 @@ int mu_parse_config (const char *file, const char *progname,
                     struct mu_cfg_param *progparam, int flags,
                     void *target_ptr) MU_CFG_DEPRECATED;
 
-int mu_cfg_parse_boolean (const char *str, int *res);
-
 extern int mu_cfg_parser_verbose;
 extern size_t mu_cfg_error_count;
 
diff --git a/include/mailutils/opt.h b/include/mailutils/opt.h
new file mode 100644
index 0000000..de84d21
--- /dev/null
+++ b/include/mailutils/opt.h
@@ -0,0 +1,169 @@
+/* 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_OPT_H
+#define _MAILUTILS_OPT_H
+#include <stdio.h>
+#include <mailutils/types.h>
+#include <mailutils/list.h>
+#include <mailutils/util.h>
+#include <mailutils/cctype.h>
+
+extern char *mu_progname;
+extern char *mu_absprogname;
+
+void mu_set_progname (char const *arg);
+
+#define MU_OPTION_DEFAULT        0
+#define MU_OPTION_ARG_OPTIONAL   0x01
+#define MU_OPTION_HIDDEN         0x02
+#define MU_OPTION_ALIAS          0x04
+#define MU_OPTION_IMMEDIATE      0x08
+
+struct mu_parseopt;
+
+struct mu_option
+{
+  char *opt_long;         /* Long option name */
+  int opt_short;          /* Short option character */
+  char *opt_arg;          /* Argument name */
+  int opt_flags;          /* Flags (see above) */  
+  char *opt_doc;          /* Human-readable documentation */
+  mu_c_type_t opt_type;   /* Option type */
+  void *opt_ptr;          /* Data pointer */
+  void (*opt_set) (struct mu_parseopt *, struct mu_option *, char const *);
+                          /* Function to set the option */
+};
+
+#define MU_OPTION_GROUP(text) { NULL, 0, NULL, 0, text }
+#define MU_OPTION_END { NULL, 0, NULL, 0, NULL }
+
+#define MU_OPTION_IS_END(opt)                                  \
+  (!(opt)->opt_long && !(opt)->opt_short && !(opt)->opt_doc)
+
+#define MU_OPTION_IS_OPTION(opt) \
+  ((opt)->opt_short || (opt)->opt_long)
+#define MU_OPTION_IS_GROUP_HEADER(opt)                 \
+  (!MU_OPTION_IS_OPTION(opt) && (opt)->opt_doc)
+#define MU_OPTION_IS_VALID_SHORT_OPTION(opt) \
+  ((opt)->opt_short > 0 && (opt)->opt_short < 127 && \
+   mu_isalnum ((opt)->opt_short))
+#define MU_OPTION_IS_VALID_LONG_OPTION(opt) \
+  ((opt)->opt_long != NULL)
+
+typedef struct mu_option_cache *mu_option_cache_ptr_t;
+
+struct mu_option_cache
+{
+  struct mu_option *cache_opt;
+  char *cache_arg;
+};
+
+#define MU_PARSEOPT_DEFAULT        0
+/* Don't ignore the first element of ARGV.  By default it is the program
+   name */
+#define MU_PARSEOPT_ARGV0          0x00000001
+/* Ignore command line errors. */
+#define MU_PARSEOPT_IGNORE_ERRORS  0x00000002
+/* Don't order arguments so that options come first. */
+#define MU_PARSEOPT_IN_ORDER       0x00000004
+/* Don't provide standard options: -h, --help, --usage, --version */
+#define MU_PARSEOPT_NO_STDOPT      0x00000008
+/* Don't exit on errors */
+#define MU_PARSEOPT_NO_ERREXIT     0x00000010
+/* Apply all options immediately */
+#define MU_PARSEOPT_IMMEDIATE      0x00000020
+
+/* Don't sort options */
+#define MU_PARSEOPT_NO_SORT        0x00001000
+
+#define MU_PARSEOPT_PROG_NAME      0x00002000
+#define MU_PARSEOPT_PROG_DOC       0x00004000
+#define MU_PARSEOPT_PROG_ARGS      0x00008000
+#define MU_PARSEOPT_BUG_ADDRESS    0x00010000
+#define MU_PARSEOPT_PACKAGE_NAME   0x00020000
+#define MU_PARSEOPT_PACKAGE_URL    0x00040000
+#define MU_PARSEOPT_DATA           0x00080000
+#define MU_PARSEOPT_HELP_HOOK      0x00100000
+
+/* Reuse mu_parseopt struct initialized previously */
+#define MU_PARSEOPT_REUSE          0x80000000
+/* Mask for immutable flag bits */
+#define MU_PARSEOPT_IMMUTABLE_MASK 0xFFFFF000
+
+
+struct mu_parseopt
+{
+  /* Input data: */
+  int po_argc;                     /* Number of argiments */
+  char **po_argv;                  /* Array of arguments */
+  size_t po_optc;                  /* Number of elements in optv */
+  struct mu_option **po_optv;      /* Array of ptrs to option structures */ 
+  int po_flags;                        
+
+  char *po_data;                   /* Call-specific data */
+  
+  /* Informational: */
+  char const *po_prog_name;
+  char const *po_prog_doc;     
+  char const *po_prog_args;
+  char const *po_bug_address;
+  char const *po_package_name;
+  char const *po_package_url;
+
+  void (*po_help_hook) (FILE *stream); /* FIXME: should take mu_Stream_t ?*/
+  
+  /* Output data */
+  int po_ind;                      /* Index of the next option */
+  int po_opterr;                   /* Index of the element in po_argv that
+                                     caused last error, or -1 if no errors */
+  mu_list_t po_optlist;
+  
+  /* Auxiliary data */
+  char *po_cur;                    /* Points to the next character */
+  int po_chr;                      /* Single-char option */
+  
+  /* The following two keep the position of the first non-optional argument
+     and the number of contiguous non-optional arguments after it.
+     Obviously, the following holds true:
+
+         arg_start + arg_count == opt_ind
+
+     If permutation is not allowed (MU_OPTION_PARSE_IN_ORDER flag is set),
+     arg_count is always 0.
+  */
+  int po_arg_start;
+  int po_arg_count;
+
+  unsigned po_permuted:1;           /* Whether the arguments were permuted */
+};
+
+int mu_parseopt (struct mu_parseopt *p,
+                int argc, char **argv, struct mu_option **optv,
+                int flags);
+
+int mu_parseopt_apply (struct mu_parseopt *p);
+void mu_parseopt_free (struct mu_parseopt *p);
+
+void mu_option_describe_options (struct mu_option **optbuf, size_t optcnt);
+void mu_program_help (struct mu_parseopt *p);
+void mu_program_usage (struct mu_parseopt *p);
+
+void mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
+                         char const *arg);
+
+#endif
diff --git a/include/mailutils/util.h b/include/mailutils/util.h
index b5bc303..1d994dd 100644
--- a/include/mailutils/util.h
+++ b/include/mailutils/util.h
@@ -152,6 +152,36 @@ int mu_getpass (mu_stream_t in, mu_stream_t out, const 
char *prompt,
                char **passptr);
 
   /* ----------------------- */
+  /* String conversions.     */
+  /* ----------------------- */
+
+enum mu_c_type
+  {
+    mu_c_string,
+    mu_c_short,
+    mu_c_ushort,
+    mu_c_int,
+    mu_c_uint,
+    mu_c_long,
+    mu_c_ulong,
+    mu_c_size,
+    mu_c_off,
+    mu_c_time,
+    mu_c_bool,
+    mu_c_ipv4,
+    mu_c_cidr,
+    mu_c_host,
+    mu_c_incr,        /* C int value, incremented each time mu_str_to_c is
+                        invoked */
+    mu_c_void         /* No type.  Keep it the last */
+  };
+
+typedef enum mu_c_type mu_c_type_t;
+extern char const *mu_c_type_str[];
+int mu_str_to_c (char const *string, mu_c_type_t type, void *tgt,
+                char **errmsg);
+  
+  /* ----------------------- */
   /* Assorted functions.     */
   /* ----------------------- */
 int mu_getmaxfd (void);
@@ -208,7 +238,6 @@ int mu_file_safety_compose (int *res, const char *name, int 
defval);
 int mu_file_mode_to_safety_criteria (int mode);
 int mu_safety_criteria_to_file_mode (int crit);
   
-  
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/manlock.c b/lib/manlock.c
index cdb65b1..ded7e0b 100644
--- a/lib/manlock.c
+++ b/lib/manlock.c
@@ -185,9 +185,9 @@ manlock_open_mailbox (mu_mailbox_t *pmbox, const char 
*mailbox_name, int def,
 
 
 struct mu_cfg_param manlock_param[] = {
-  { "enable", mu_cfg_bool, &manlock_mandatory_locking, 0, NULL,
+  { "enable", mu_c_bool, &manlock_mandatory_locking, 0, NULL,
     N_("Enable mandatory locking.") },
-  { "lock-directory", mu_cfg_string, &manlock_lock_dir, 0, NULL,
+  { "lock-directory", mu_c_string, &manlock_lock_dir, 0, NULL,
     N_("Set directory for mandatory lock files.") },
   { NULL }
 };
diff --git a/lib/tcpwrap.c b/lib/tcpwrap.c
index 585d1a1..f4df64e 100644
--- a/lib/tcpwrap.c
+++ b/lib/tcpwrap.c
@@ -53,17 +53,17 @@ mu_tcpwrapper_access (int fd)
 }
 
 struct mu_cfg_param tcpwrapper_param[] = {
-  { "enable", mu_cfg_bool, &mu_tcp_wrapper_enable, 0, NULL,          
+  { "enable", mu_c_bool, &mu_tcp_wrapper_enable, 0, NULL,            
     N_("Enable TCP wrapper access control.  Default is \"yes\".") },         
-  { "daemon", mu_cfg_string, &mu_tcp_wrapper_daemon, 0, NULL,     
+  { "daemon", mu_c_string, &mu_tcp_wrapper_daemon, 0, NULL,     
     N_("Set daemon name for TCP wrapper lookups.  Default is program name."), 
     N_("name") },                                                            
-  { "allow-table", mu_cfg_string, &hosts_allow_table,
+  { "allow-table", mu_c_string, &hosts_allow_table,
     0, NULL,
     N_("Use file for positive client address access control "                
        "(default: /etc/hosts.allow)."),                                        
      
     N_("file") },                                                            
-  { "deny-table", mu_cfg_string, &hosts_deny_table,
+  { "deny-table", mu_c_string, &hosts_deny_table,
     0, NULL,                                             
     N_("Use file for negative client address access control "                
        "(default: /etc/hosts.deny)."),                                       
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 9d0c3bf..7a5270c 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -18,7 +18,7 @@
 
 SUBDIRS = \
  auth base address list sockaddr cidr cfg diag\
- filter mailbox mailer mime msgset server string stream stdstream\
+ filter mailbox mailer mime msgset opt server string stream stdstream\
  property url imapio datetime . tests 
 
 lib_LTLIBRARIES = libmailutils.la
@@ -42,6 +42,7 @@ libmailutils_la_LIBADD = \
  mailer/libmailer.la\
  mime/libmime.la\
  msgset/libmsgset.la\
+ opt/libopt.la\
  property/libproperty.la\
  server/libserver.la\
  string/libstring.la\
diff --git a/libmailutils/cfg/format.c b/libmailutils/cfg/format.c
index 27801d2..d94c878 100644
--- a/libmailutils/cfg/format.c
+++ b/libmailutils/cfg/format.c
@@ -263,35 +263,38 @@ mu_cfg_format_node (mu_stream_t stream, const 
mu_cfg_node_t *node, int flags)
 
 
 const char *
-mu_cfg_data_type_string (enum mu_cfg_param_data_type type)
+mu_c_type_string (int type)
 {
   switch (type)
     {
-    case mu_cfg_string:
+    case mu_c_string:
       return N_("string");
-    case mu_cfg_short:
-    case mu_cfg_ushort:
-    case mu_cfg_int:
-    case mu_cfg_uint:
-    case mu_cfg_long:
-    case mu_cfg_ulong:
-    case mu_cfg_size:
-    case mu_cfg_off:
+    case mu_c_short:
+    case mu_c_ushort:
+    case mu_c_int:
+    case mu_c_uint:
+    case mu_c_long:
+    case mu_c_ulong:
+    case mu_c_size:
+    case mu_c_off:
+    case mu_c_incr:
       return N_("number");
-    case mu_cfg_time:
+    case mu_c_time:
       return N_("time");
-    case mu_cfg_bool:
+    case mu_c_bool:
       return N_("boolean");
-    case mu_cfg_ipv4:
+    case mu_c_ipv4:
       return N_("ipv4");
-    case mu_cfg_cidr:
+    case mu_c_cidr:
       return N_("cidr");
-    case mu_cfg_host:
+    case mu_c_host:
       return N_("host");
-    case mu_cfg_callback:
-      return N_("string");
     case mu_cfg_section:
       return N_("section");
+    case mu_cfg_callback:
+      return N_("callback");
+    default:
+      break;
     }
   return N_("unknown");
 }
@@ -361,13 +364,13 @@ format_param (mu_stream_t stream, struct mu_cfg_param 
*param, int level)
                      param->ident,
                      gettext (param->argname ?
                               param->argname : N_("arg")),
-       gettext (mu_cfg_data_type_string (MU_CFG_TYPE (param->type))));
+       gettext (mu_c_type_string (MU_CFG_TYPE (param->type))));
   else
     mu_stream_printf (stream, "%s <%s: %s>;\n",
                      param->ident,
                      gettext (param->argname ?
                               param->argname : N_("arg")),
-                     gettext (mu_cfg_data_type_string (param->type)));
+                     gettext (mu_c_type_string (param->type)));
 }
 
 static void format_container (mu_stream_t stream, struct mu_cfg_cont *cont,
diff --git a/libmailutils/cfg/parser.y b/libmailutils/cfg/parser.y
index fe76ef1..6877063 100644
--- a/libmailutils/cfg/parser.y
+++ b/libmailutils/cfg/parser.y
@@ -40,6 +40,7 @@
 #include <mailutils/cctype.h>
 #include <mailutils/stream.h>
 #include <mailutils/stdstream.h>
+#include <mailutils/cidr.h>
 
 int mu_cfg_parser_verbose;
 static mu_list_t /* of mu_cfg_node_t */ parse_node_list; 
@@ -781,385 +782,52 @@ pop_section (struct scan_tree_data *dat)
   return sec;
 }
 
-#define STRTONUM(s, type, base, res, limit, loc)                       \
-  {                                                                    \
-    type sum = 0;                                                      \
-                                                                       \
-    for (; *s; s++)                                                    \
-      {                                                                        
\
-       type x;                                                         \
-                                                                       \
-       if ('0' <= *s && *s <= '9')                                     \
-         x = sum * base + *s - '0';                                    \
-       else if (base == 16 && 'a' <= *s && *s <= 'f')                  \
-         x = sum * base + *s - 'a';                                    \
-       else if (base == 16 && 'A' <= *s && *s <= 'F')                  \
-         x = sum * base + *s - 'A';                                    \
-       else                                                            \
-         break;                                                        \
-       if (x <= sum)                                                   \
-         {                                                             \
-           mu_diag_at_locus (MU_LOG_ERROR, loc,                        \
-                             _("numeric overflow"));                   \
-           mu_cfg_error_count++;                                       \
-           return 1;                                                   \
-         }                                                             \
-       else if (limit && x > limit)                                    \
-         {                                                             \
-           mu_diag_at_locus (MU_LOG_ERROR, loc,                        \
-                             _("value out of allowed range"));         \
-           mu_cfg_error_count++;                                       \
-           return 1;                                                   \
-         }                                                             \
-       sum = x;                                                        \
-      }                                                                        
\
-    res = sum;                                                         \
-  }
-
-#define STRxTONUM(s, type, res, limit, loc)                            \
-  {                                                                    \
-    int base;                                                          \
-    if (*s == '0')                                                     \
-      {                                                                        
\
-       s++;                                                            \
-       if (*s == 0)                                                    \
-         base = 10;                                                    \
-       else if (*s == 'x' || *s == 'X')                                \
-         {                                                             \
-           s++;                                                        \
-           base = 16;                                                  \
-         }                                                             \
-       else                                                            \
-         base = 8;                                                     \
-      } else                                                           \
-      base = 10;                                                       \
-    STRTONUM (s, type, base, res, limit, loc);                         \
-  }
-
-#define GETUNUM(str, type, res, loc)                                   \
-  {                                                                    \
-    type tmpres;                                                       \
-    const char *s = str;                                               \
-    STRxTONUM (s, type, tmpres, 0, loc);                               \
-    if (*s)                                                            \
-      {                                                                        
\
-       mu_diag_at_locus (MU_LOG_ERROR, loc,                            \
-                         _("not a number (stopped near `%s')"),        \
-                         s);                                           \
-       mu_cfg_error_count++;                                           \
-       return 1;                                                       \
-      }                                                                        
\
-    res = tmpres;                                                      \
-  }
-
-#define GETSNUM(str, type, res, loc)                                   \
-  {                                                                    \
-    unsigned type tmpres;                                              \
-    const char *s = str;                                               \
-    int sign;                                                          \
-    unsigned type limit;                                               \
-                                                                       \
-    if (*s == '-')                                                     \
-      {                                                                        
\
-       sign = 1;                                                       \
-       s++;                                                            \
-       limit = TYPE_MINIMUM (type);                                    \
-       limit = - limit;                                                \
-      }                                                                        
\
-    else                                                               \
-      {                                                                        
\
-       sign = 0;                                                       \
-       limit = TYPE_MAXIMUM (type);                                    \
-      }                                                                        
\
-                                                                       \
-    STRxTONUM (s, unsigned type, tmpres, limit, loc);                  \
-    if (*s)                                                            \
-      {                                                                        
\
-       mu_diag_at_locus (MU_LOG_ERROR, loc,                            \
-                         _("not a number (stopped near `%s')"),        \
-                         s);                                           \
-       mu_cfg_error_count++;                                           \
-       return 1;                                                       \
-      }                                                                        
\
-    res = sign ? - tmpres : tmpres;                                    \
-  }
-
-static int
-parse_ipv4 (struct scan_tree_data *sdata, const struct mu_locus *locus,
-           const char *str, struct in_addr *res)
-{
-  struct in_addr addr;
-  if (inet_aton (str, &addr) == 0)
-    {
-      mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus, _("not an IPv4"));
-      mu_cfg_error_count++;
-      return 1;
-    }
-  addr.s_addr = ntohl (addr.s_addr);
-  *res = addr;
-  return 0;
-}
-
-static int
-parse_host (struct scan_tree_data *sdata, const struct mu_locus *locus,
-           const char *str, struct in_addr *res)
-{
-  struct in_addr addr;
-  struct hostent *hp = gethostbyname (str);
-  if (hp)
-    {
-      addr.s_addr = *(unsigned long *)hp->h_addr;
-    }
-  else if (inet_aton (str, &addr) == 0)
-    {
-      mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
-                       _("cannot resolve hostname `%s'"),
-                       str);
-      mu_cfg_error_count++;
-      return 1;
-    }
-  addr.s_addr = ntohl (addr.s_addr);
-  *res = addr;
-  return 0;
-}
-
 static int
-parse_cidr (struct scan_tree_data *sdata, const struct mu_locus *locus,
-           const char *str, mu_cfg_cidr_t *res)
+valcvt (const struct mu_locus *locus,
+       void *tgt, mu_c_type_t type, mu_config_value_t *val)
 {
-  struct in_addr addr;
-  unsigned long mask;
-  char astr[16];
-  const char *p, *s;
-  
-  p = strchr (str, '/');
-  if (p)
-    {
-      int len = p - str;
-      if (len > sizeof astr - 1)
-       {
-         mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
-                           _("not a valid IPv4 address in CIDR"));
-         mu_cfg_error_count++;
-         return 1;
-       }
-      memcpy (astr, str, len);
-      astr[len] = 0;
-      if (inet_aton (astr, &addr) == 0)
-       {
-         mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
-                           _("not a valid IPv4 address in CIDR"));
-         mu_cfg_error_count++;
-         return 1;
-       }
-      addr.s_addr = ntohl (addr.s_addr);
-      
-      p++;
-      s = p;
-      STRxTONUM (s, unsigned long, mask, 0, locus);
-      if (*s == '.')
-       {
-         struct in_addr a;
-         if (inet_aton (p, &a) == 0)
-           {
-             mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
-                               _("not a valid network in CIDR"));
-             mu_cfg_error_count++;
-             return 1;
-           }
-         a.s_addr = ntohl (a.s_addr);
-         for (mask = 0; (a.s_addr & 1) == 0 && mask < 32; )
-           {
-             mask++;
-             a.s_addr >>= 1;
-           }
-         mask = 32 - mask;
-       }
-      else if (mask > 32)
-       {
-         mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
-                           _("not a valid network mask in CIDR"));
-         mu_cfg_error_count++;
-         return 1;
-       }
-    }
-  else
-    {
-      int i;
-      unsigned short x;
-      addr.s_addr = 0;
-      
-      p = str;
-      for (i = 0; i < 3; i++)
-       {
-         STRxTONUM (p, unsigned short, x, 255, locus);
-         if (*p != '.')
-           break;
-         addr.s_addr = (addr.s_addr << 8) + x;
-       }
-      
-      if (*p)
-       {
-         mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
-                           _("not a CIDR (stopped near `%s')"),
-                           p);
-         mu_cfg_error_count++;
-         return 1;
-       }
-      
-      mask = i * 8;
-      
-      addr.s_addr <<= (4 - i) * 8;
-    }
+  int rc;
+  char *errmsg;
   
-  res->addr = addr;
-  res->mask = mask;
-  return 0;
-}
-
-int
-mu_cfg_parse_boolean (const char *str, int *res)
-{
-  if (strcmp (str, "yes") == 0
-      || strcmp (str, "on") == 0
-      || strcmp (str, "t") == 0
-      || strcmp (str, "true") == 0
-      || strcmp (str, "1") == 0)
-    *res = 1;
-  else if (strcmp (str, "no") == 0
-          || strcmp (str, "off") == 0
-          || strcmp (str, "nil") == 0
-          || strcmp (str, "false") == 0
-          || strcmp (str, "0") == 0)
-    *res = 0;
-  else
-    return 1;
-  return 0;
-}
-
-static int
-parse_bool (struct scan_tree_data *sdata, const struct mu_locus *locus,
-           const char *str, int *res)
-{
-  if (mu_cfg_parse_boolean (str, res))
-    {
-      mu_diag_at_locus (MU_LOG_ERROR, locus, _("not a boolean"));
-      mu_cfg_error_count++;
-      return 1;
-    }
-  return 0;
-}
-
-static int
-valcvt (struct scan_tree_data *sdata, const struct mu_locus *locus,
-       void *tgt,
-       enum mu_cfg_param_data_type type, mu_config_value_t *val)
-{
   if (val->type != MU_CFG_STRING)
     {
       mu_diag_at_locus (MU_LOG_ERROR, locus, _("expected string value"));
       mu_cfg_error_count++;
       return 1;
     }
-  switch (type)
+
+  rc = mu_str_to_c (val->v.string, type, tgt, &errmsg);
+  if (rc)
     {
-    case mu_cfg_string:
-      {
-       char *s = mu_strdup (val->v.string);
-       /* FIXME: free tgt? */
-       *(char**)tgt = s;
-       break;
-      }
-      
-    case mu_cfg_short:
-      GETUNUM (val->v.string, short, *(short*)tgt, locus);
-      break;
-      
-    case mu_cfg_ushort:
-      GETUNUM (val->v.string, unsigned short, *(unsigned short*)tgt, locus);
-      break;
-      
-    case mu_cfg_int:
-      GETSNUM (val->v.string, int, *(int*)tgt, locus);
-      break;
-      
-    case mu_cfg_uint:
-      GETUNUM (val->v.string, unsigned int, *(unsigned int*)tgt, locus);
-      break;
-      
-    case mu_cfg_long:
-      GETSNUM (val->v.string, long, *(long*)tgt, locus);
-      break;
-      
-    case mu_cfg_ulong:
-      GETUNUM (val->v.string, unsigned long, *(unsigned long*)tgt, locus);
-      break;
-      
-    case mu_cfg_size:
-      GETUNUM (val->v.string, size_t, *(size_t*)tgt, locus);
-      break;
-      
-    case mu_cfg_off:
-      mu_diag_at_locus (MU_LOG_ERROR, locus, _("not implemented yet"));
-      mu_cfg_error_count++;
-      /* GETSNUM(node->tag_label, off_t, *(off_t*)tgt); */
-      return 1;
-      
-    case mu_cfg_time:
-      GETUNUM (val->v.string, time_t, *(time_t*)tgt, locus);
-      break;
-      
-    case mu_cfg_bool:
-      if (parse_bool (sdata, locus, val->v.string, (int*) tgt))
-       return 1;
-      break;
-      
-    case mu_cfg_ipv4:
-      if (parse_ipv4 (sdata, locus, val->v.string, (struct in_addr *)tgt))
-       return 1;
-      break;
-      
-    case mu_cfg_cidr:
-      if (parse_cidr (sdata, locus, val->v.string, (mu_cfg_cidr_t *)tgt))
-       return 1;
-      break;
-      
-    case mu_cfg_host:
-      if (parse_host (sdata, locus, val->v.string, (struct in_addr *)tgt))
-       return 1;
-      break;
-      
-    default:
-      return 1;
+      mu_diag_at_locus (MU_LOG_ERROR, locus, "%s",
+                       errmsg ? errmsg : mu_strerror (rc));
+      free (errmsg);
     }
-  return 0;
+  return rc;
 }
 
 struct set_closure
 {
   mu_list_t list;
-  enum mu_cfg_param_data_type type;
+  int type;
   struct scan_tree_data *sdata;
   const struct mu_locus *locus;
 };
 
 static size_t config_type_size[] = {
-  sizeof (char*),          /* mu_cfg_string */
-  sizeof (short),          /* mu_cfg_short */
-  sizeof (unsigned short), /* mu_cfg_ushort */
-  sizeof (int),            /* mu_cfg_int */
-  sizeof (unsigned),       /* mu_cfg_uint */
-  sizeof (long),           /* mu_cfg_long */
-  sizeof (unsigned long),  /* mu_cfg_ulong */
-  sizeof (size_t),         /* mu_cfg_size */
-  sizeof (mu_off_t),       /* mu_cfg_off */
-  sizeof (time_t),         /* mu_cfg_time */
-  sizeof (int),            /* mu_cfg_bool */
-  sizeof (struct in_addr), /* mu_cfg_ipv4 */
-  sizeof (mu_cfg_cidr_t),  /* mu_cfg_cidr */
-  sizeof (struct in_addr), /* mu_cfg_host */
-  0,                       /* mu_cfg_callback */
-  0,                       /* mu_cfg_section */
+  [mu_c_string] = sizeof (char*),          
+  [mu_c_short]  = sizeof (short),          
+  [mu_c_ushort] = sizeof (unsigned short), 
+  [mu_c_int]    = sizeof (int),            
+  [mu_c_uint]   = sizeof (unsigned),       
+  [mu_c_long]   = sizeof (long),           
+  [mu_c_ulong]  = sizeof (unsigned long),  
+  [mu_c_size]   = sizeof (size_t),         
+  [mu_c_time]   = sizeof (time_t),         
+  [mu_c_bool]   = sizeof (int),            
+  [mu_c_ipv4]   = sizeof (struct in_addr), 
+  [mu_c_cidr]   = sizeof (struct mu_cidr), 
+  [mu_c_host]   = sizeof (struct in_addr), 
 };
 
 static int
@@ -1188,7 +856,7 @@ _set_fun (void *item, void *data)
       return 1;
     }
   
-  if (valcvt (clos->sdata, clos->locus, &tgt, clos->type, val) == 0)
+  if (valcvt (clos->locus, &tgt, clos->type, val) == 0)
     mu_list_append (clos->list, tgt);
   return 0;
 }
@@ -1274,7 +942,7 @@ parse_param (struct scan_tree_data *sdata, const 
mu_cfg_node_t *node)
        return 1;
     }
   else
-    return valcvt (sdata, &node->locus, tgt, clos.type, node->label);
+    return valcvt (&node->locus, tgt, clos.type, node->label);
   
   return 0;
 }
diff --git a/libmailutils/mailer/Makefile.am b/libmailutils/opt/Makefile.am
similarity index 77%
copy from libmailutils/mailer/Makefile.am
copy to libmailutils/opt/Makefile.am
index 2f78194..d229c45 100644
--- a/libmailutils/mailer/Makefile.am
+++ b/libmailutils/opt/Makefile.am
@@ -1,5 +1,5 @@
 # GNU Mailutils -- a suite of utilities for electronic mail
-# Copyright (C) 2010-2012, 2014-2016 Free Software Foundation, Inc.
+# Copyright (C) 2016 Free Software Foundation, Inc.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -15,10 +15,12 @@
 # Public License along with this library.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-noinst_LTLIBRARIES = libmailer.la
+noinst_LTLIBRARIES = libopt.la
 
-libmailer_la_SOURCES = \
- mailer.c\
- progmailer.c
+libopt_la_SOURCES = \
+ opt.c\
+ help.c\
+ progname.c
 
-AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
+AM_CPPFLAGS = \
+  @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
diff --git a/libmailutils/opt/help.c b/libmailutils/opt/help.c
new file mode 100644
index 0000000..c3d9a6f
--- /dev/null
+++ b/libmailutils/opt/help.c
@@ -0,0 +1,345 @@
+/* help.c -- 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/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/alloc.h>
+#include <mailutils/opt.h>
+#include <mailutils/cctype.h>
+#include <mailutils/nls.h>
+
+#define LMARGIN 2
+#define DESCRCOLUMN 30
+#define RMARGIN 79
+#define GROUPCOLUMN 2
+#define USAGECOLUMN 13
+
+static void
+indent (size_t start, size_t col)
+{
+  for (; start < col; start++)
+    putchar (' ');
+}
+
+static void
+print_option_descr (const char *descr, size_t lmargin, size_t rmargin)
+{
+  while (*descr)
+    {
+      size_t s = 0;
+      size_t i;
+      size_t width = rmargin - lmargin;
+      
+      for (i = 0; ; i++)
+       {
+         if (descr[i] == 0 || descr[i] == ' ' || descr[i] == '\t')
+           {
+             if (i > width)
+               break;
+             s = i;
+             if (descr[i] == 0)
+               break;
+           }
+       }
+      fwrite (descr, 1, s, stdout);
+      fputc ('\n', stdout);
+      descr += s;
+      if (*descr)
+       {
+         indent (0, lmargin);
+         descr++;
+       }
+    }
+}
+
+
+static size_t
+print_option (struct mu_option **optbuf, size_t optcnt, size_t num,
+             int *argsused)
+{
+  struct mu_option *opt = optbuf[num];
+  size_t next, i;
+  int delim;
+  int w;
+  
+  if (MU_OPTION_IS_GROUP_HEADER (opt))
+    {
+      if (num)
+       putchar ('\n');
+      indent (0, GROUPCOLUMN);
+      print_option_descr (gettext (opt->opt_doc), GROUPCOLUMN, RMARGIN);
+      putchar ('\n');
+      return num + 1;
+    }
+
+  /* count aliases */
+  for (next = num + 1;
+       next < optcnt && optbuf[next]->opt_flags & MU_OPTION_ALIAS;
+       next++);
+
+  if (opt->opt_flags & MU_OPTION_HIDDEN)
+    return next;
+
+  w = 0;
+  for (i = num; i < next; i++)
+    {
+      if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]))
+       {
+         if (w == 0)
+           {
+             indent (0, LMARGIN);
+             w = LMARGIN;
+           }
+         else
+           w += printf (", ");
+         w += printf ("-%c", optbuf[i]->opt_short);
+         delim = ' ';
+       }
+    }
+  
+  for (i = num; i < next; i++)
+    {
+      if (MU_OPTION_IS_VALID_LONG_OPTION (optbuf[i]))
+       {
+         if (w == 0)
+           {
+             indent (0, LMARGIN);
+             w = LMARGIN;
+           }
+         else
+           w += printf (", ");
+         w += printf ("--%s", optbuf[i]->opt_long);
+         delim = '=';
+       }
+    }
+  
+  if (opt->opt_arg)
+    {
+      *argsused = 1;
+      if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL)
+       {
+         if (delim == '=')
+           w += printf ("[=%s]", gettext (opt->opt_arg));
+         else
+           w += printf ("[%s]", gettext (opt->opt_arg));
+       }
+      else
+       w += printf ("%c%s", delim, gettext (opt->opt_arg));
+    }
+  if (w >= DESCRCOLUMN)
+    {
+      putchar ('\n');
+      w = 0;
+    }
+  indent (w, DESCRCOLUMN);
+  print_option_descr (gettext (opt->opt_doc), DESCRCOLUMN, RMARGIN);
+
+  return next;
+}
+
+void
+mu_option_describe_options (struct mu_option **optbuf, size_t optcnt)
+{
+  unsigned i;
+  int argsused = 0;
+
+  for (i = 0; i < optcnt; )
+    i = print_option (optbuf, optcnt, i, &argsused);
+  putchar ('\n');
+
+  if (argsused)
+    {
+      print_option_descr (_("Mandatory or optional arguments to long options 
are also mandatory or optional for any corresponding short options."), 0, 
RMARGIN);
+      putchar ('\n');
+    }
+}
+
+void
+mu_program_help (struct mu_parseopt *po)
+{
+  printf ("%s", _("Usage:"));
+  if (po->po_prog_name)
+    printf (" %s", po->po_prog_name);
+  printf (" [%s]...", _("OPTION"));
+  if (po->po_prog_args)
+    printf (" %s", gettext (po->po_prog_args));
+  putchar ('\n');
+  
+  if (po->po_prog_doc)
+    print_option_descr (gettext (po->po_prog_doc), 0, RMARGIN);
+  putchar ('\n');
+
+  mu_option_describe_options (po->po_optv, po->po_optc);
+
+  if (po->po_help_hook)
+    po->po_help_hook (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);
+
+  if (po->po_package_name && po->po_package_url)
+    printf (_("%s home page: <%s>\n"),
+           po->po_package_name, po->po_package_url);
+}
+
+static struct mu_option **option_tab;
+
+static int
+cmpidx_short (const void *a, const void *b)
+{
+  unsigned const *ai = (unsigned const *)a;
+  unsigned const *bi = (unsigned const *)b;
+
+  return option_tab[*ai]->opt_short - option_tab[*bi]->opt_short;
+}
+  
+static int
+cmpidx_long (const void *a, const void *b)
+{
+  unsigned const *ai = (unsigned const *)a;
+  unsigned const *bi = (unsigned const *)b;
+  struct mu_option const *ap = option_tab[*ai];
+  struct mu_option const *bp = option_tab[*bi];
+  return strcmp (ap->opt_long, bp->opt_long);
+}
+
+void
+mu_program_usage (struct mu_parseopt *po)
+{
+  unsigned i;
+  unsigned n;
+  char buf[RMARGIN+1];
+  unsigned *idxbuf;
+  unsigned nidx;
+
+  struct mu_option **optbuf = po->po_optv;
+  size_t optcnt = po->po_optc;
+  
+#define FLUSH                                                          \
+  do                                                                   \
+    {                                                                  \
+      buf[n] = 0;                                                      \
+      printf ("%s\n", buf);                                            \
+      n = USAGECOLUMN;                                                 \
+      memset (buf, ' ', n);                                            \
+    }                                                                  \
+  while (0)
+#define ADDC(c)                                                                
\
+  do                                                                   \
+    {                                                                  \
+      if (n == RMARGIN) FLUSH;                                         \
+      buf[n++] = c;                                                    \
+    }                                                                  \
+  while (0)
+
+  option_tab = optbuf;
+  
+  idxbuf = mu_calloc (optcnt, sizeof (idxbuf[0]));
+
+  n = snprintf (buf, sizeof buf, "%s %s ", _("Usage:"),        mu_progname);
+  
+  /* Print a list of short options without arguments. */
+  for (i = nidx = 0; i < optcnt; i++)
+    if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]) && !optbuf[i]->opt_arg)
+      idxbuf[nidx++] = i;
+
+  if (nidx)
+    {
+      qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
+
+      ADDC ('[');
+      ADDC ('-');
+      for (i = 0; i < nidx; i++)
+       {
+         ADDC (optbuf[idxbuf[i]]->opt_short);
+       }
+      ADDC (']');
+    }
+
+  /* Print a list of short options with arguments. */
+  for (i = nidx = 0; i < optcnt; i++)
+    {
+      if (MU_OPTION_IS_VALID_SHORT_OPTION (optbuf[i]) && optbuf[i]->opt_arg)
+       idxbuf[nidx++] = i;
+    }
+
+  if (nidx)
+    {
+      qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_short);
+    
+      for (i = 0; i < nidx; i++)
+       {
+         struct mu_option *opt = optbuf[idxbuf[i]];
+         const char *arg = gettext (opt->opt_arg);
+         size_t len = 5 + strlen (arg) + 1;
+         
+         if (n + len > RMARGIN) FLUSH;
+         buf[n++] = ' ';
+         buf[n++] = '[';
+         buf[n++] = '-';
+         buf[n++] = opt->opt_short;
+         buf[n++] = ' ';
+         strcpy (&buf[n], arg);
+         n += strlen (arg);
+         buf[n++] = ']';
+       }
+    }
+  
+  /* Print a list of long options */
+  for (i = nidx = 0; i < optcnt; i++)
+    {
+      if (MU_OPTION_IS_VALID_LONG_OPTION (optbuf[i]))
+       idxbuf[nidx++] = i;
+    }
+
+  if (nidx)
+    {
+      qsort (idxbuf, nidx, sizeof (idxbuf[0]), cmpidx_long);
+       
+      for (i = 0; i < nidx; i++)
+       {
+         struct mu_option *opt = optbuf[idxbuf[i]];
+         const char *arg = opt->opt_arg ? gettext (opt->opt_arg) : NULL;
+         size_t len = 3 + strlen (opt->opt_long)
+                        + (arg ? 1 + strlen (arg) : 0);
+         if (n + len > RMARGIN) FLUSH;
+         buf[n++] = ' ';
+         buf[n++] = '[';
+         buf[n++] = '-';
+         buf[n++] = '-';
+         strcpy (&buf[n], opt->opt_long);
+         n += strlen (opt->opt_long);
+         if (opt->opt_arg)
+           {
+             buf[n++] = '=';
+             strcpy (&buf[n], arg);
+             n += strlen (arg);
+           }
+         buf[n++] = ']';
+       }
+    }
+
+  FLUSH;
+  free (idxbuf);
+}
+
diff --git a/libmailutils/opt/opt.c b/libmailutils/opt/opt.c
new file mode 100644
index 0000000..ba54f75
--- /dev/null
+++ b/libmailutils/opt/opt.c
@@ -0,0 +1,638 @@
+/* opt.c -- 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/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <mailutils/alloc.h>
+#include <mailutils/opt.h>
+#include <mailutils/nls.h>
+#include <mailutils/errno.h>
+
+#define EXIT_SUCCESS 0
+#define EXIT_ERROR   1
+
+/* Compare pointers to two option structs */
+static int
+optcmp (const void *a, const void *b)
+{
+  struct mu_option const *ap = *(struct mu_option const **)a;
+  struct mu_option const *bp = *(struct mu_option const **)b;
+
+  while (ap->opt_flags & MU_OPTION_ALIAS)
+    ap--;
+  while (bp->opt_flags & MU_OPTION_ALIAS)
+    bp--;
+  
+  if (MU_OPTION_IS_VALID_SHORT_OPTION (ap)
+      && MU_OPTION_IS_VALID_SHORT_OPTION (bp))
+    return ap->opt_short - bp->opt_short;
+  if (MU_OPTION_IS_VALID_LONG_OPTION (ap)
+      && MU_OPTION_IS_VALID_LONG_OPTION (bp))
+    return strcmp (ap->opt_long, bp->opt_long);
+  if (MU_OPTION_IS_VALID_LONG_OPTION (ap))
+    return 1;
+  return -1;
+}
+
+/* Sort a group of options in OPTBUF, starting at index START (first
+   option slot after a group header (if any).  The group spans up to
+   next group header or end of options */
+static size_t
+sort_group (struct mu_option **optbuf, size_t start)
+{
+  size_t i;
+  
+  for (i = start; optbuf[i] && !MU_OPTION_IS_GROUP_HEADER (optbuf[i]); i++)
+    ;
+  
+  qsort (&optbuf[start], i - start, sizeof (optbuf[0]), optcmp);
+  return i;
+}
+
+/* Print help summary and exit. */
+static void
+fn_help (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
+{
+  mu_program_help (po);
+  exit (EXIT_SUCCESS);
+}
+
+/* Print usage summary and exit. */
+static void
+fn_usage (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
+{
+  mu_program_usage (po);
+  exit (EXIT_SUCCESS);
+}
+
+/* Default options */
+struct mu_option mu_default_options[] = {
+  MU_OPTION_GROUP(""),
+  { "help",    'h', NULL, MU_OPTION_IMMEDIATE, N_("give this help list"),
+    mu_c_string, NULL, fn_help },
+  { "version", 'V', NULL, MU_OPTION_IMMEDIATE, N_("print program version"),
+    mu_c_string, NULL, /* FIXME: fn_version */ },
+  { "usage",   0,   NULL, MU_OPTION_IMMEDIATE, N_("give a short usage 
message"),
+    mu_c_string, NULL, fn_usage
+  },
+  MU_OPTION_END
+};
+
+/* Output error message */
+static void
+parse_error (struct mu_parseopt *po, char const *fmt, ...)
+{
+  va_list ap;
+
+  if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS)
+    return;
+
+  if (po->po_prog_name)
+    fprintf (stderr, "%s: ", po->po_prog_name);
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  fputc ('\n', stderr);
+}
+
+static void
+mu_option_cache_destroy (void *ptr)
+{
+  struct mu_option_cache *cache = ptr;
+  free (cache->cache_arg);
+  free (cache);
+}
+
+static int parseopt_apply (void *item, void *data);
+
+/* If OPT is an immediate option, evaluate it right away.  Otherwise,
+   add option OPT with argument ARG to the cache in PO. */
+void
+add_option_cache (struct mu_parseopt *po, struct mu_option *opt,
+                 char const *arg)
+{
+  struct mu_option_cache *cache = mu_alloc (sizeof (*cache));
+  cache->cache_opt = opt;
+  cache->cache_arg = arg ? mu_strdup (arg) : NULL;
+
+  if (opt->opt_flags & MU_OPTION_IMMEDIATE)
+    {
+      parseopt_apply (cache, po);
+      mu_option_cache_destroy (cache);
+    }
+  else
+    {
+      mu_list_append (po->po_optlist, cache);
+    }
+}
+
+/* Find first option for which I is an alias */
+struct mu_option *
+option_unalias (struct mu_parseopt *po, int i)
+{
+  while (i > 0 && po->po_optv[i]->opt_flags & MU_OPTION_ALIAS)
+    --i;
+  return po->po_optv[i];
+}
+
+/* Find a descriptor of short option CHR */
+struct mu_option *
+find_short_option (struct mu_parseopt *po, int chr)
+{
+  size_t i;
+
+  for (i = 0; i < po->po_optc; i++)
+    {
+      if (MU_OPTION_IS_VALID_SHORT_OPTION (po->po_optv[i])
+         && po->po_optv[i]->opt_short == chr)
+       return option_unalias (po, i);
+    }
+  parse_error (po, _("unrecognized option '-%c'"), chr);
+  return NULL;
+}
+
+/* Find a descriptor of long option OPTSTR.  If it has argument, return
+   it in *ARGPTR. */
+struct mu_option *
+find_long_option (struct mu_parseopt *po, char const *optstr,
+                 char **argptr)
+{
+  size_t i;
+  size_t optlen;
+  size_t ind;
+  int found = 0;
+  
+  optlen = strcspn (optstr, "=");
+  
+  for (i = 0; i < po->po_optc; i++)
+    {
+      if (MU_OPTION_IS_VALID_LONG_OPTION (po->po_optv[i])
+         && optlen <= strlen (po->po_optv[i]->opt_long)
+         && memcmp (po->po_optv[i]->opt_long, optstr, optlen) == 0)
+       {
+         switch (found)
+           {
+           case 0:
+             ind = i;
+             found++;
+             break;
+
+           case 1:
+             if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS)
+               return NULL;
+             parse_error (po,
+                          _("option '--%*.*s' is ambiguous; possibilities:"),
+                          optlen, optlen, optstr);
+             fprintf (stderr, "--%s\n", po->po_optv[ind]->opt_long);
+             found++;
+
+           case 2:
+             fprintf (stderr, "--%s\n", po->po_optv[i]->opt_long);
+           }
+       }
+    }
+
+  switch (found)
+    {
+    case 0:
+      parse_error (po, _("unrecognized option '--%s'"), optstr);
+      break;
+      
+    case 1:
+      if (optstr[optlen])
+       ++optlen;
+      *argptr = (char *)(optstr + optlen);
+      return option_unalias (po, ind);
+
+    case 2:
+      break;
+    }
+
+  return NULL;  
+}
+
+static void
+permute (struct mu_parseopt *po)
+{
+  if (!(po->po_flags & MU_PARSEOPT_IN_ORDER) && po->po_arg_count)
+    {
+      /* Array to save arguments in */
+      char *save[2];
+      /* Number of arguments processed (at most two) */
+      int n = po->po_ind - (po->po_arg_start + po->po_arg_count);
+      
+      if (n > 2)
+       abort ();
+      
+      /* Store the processed elements away */
+      save[0] = po->po_argv[po->po_arg_start + po->po_arg_count];
+      if (n == 2)
+       save[1] = po->po_argv[po->po_arg_start + po->po_arg_count + 1];
+
+      /* Shift the array */
+      memmove (po->po_argv + po->po_arg_start + n,
+              po->po_argv + po->po_arg_start,
+              po->po_arg_count * sizeof (po->po_argv[0]));
+      
+      /* Place stored elements in the vacating slots */
+      po->po_argv[po->po_arg_start] = save[0];
+      if (n == 2)
+       po->po_argv[po->po_arg_start + 1] = save[1];
+      
+      /* Fix up start index */
+      po->po_arg_start += n;
+      po->po_permuted = 1;
+    }
+}
+
+/* Consume next option from PO.  On success, update PO members as
+   described below and return 0.  On end of options, return 1.
+
+   If the consumed option is a short option, then 
+
+     po_chr  keeps its option character, and
+     po_cur  points to the next option character to be processed
+
+   Otherwise, if the consumed option is a long one, then
+
+     po_chr  is 0
+     po_cur  points to the first character after --
+*/   
+static int
+next_opt (struct mu_parseopt *po)
+{
+  if (!*po->po_cur)
+    {
+      permute (po);
+      
+      while (1)
+       {
+         po->po_cur = po->po_argv[po->po_ind++];
+         if (!po->po_cur)
+           return 1;
+         if (po->po_cur[0] == '-' && po->po_cur[1])
+           break;
+         if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
+           {
+             if (!po->po_permuted)
+               po->po_arg_start = po->po_ind - 1;
+             po->po_arg_count++;
+             continue;
+           }
+         else
+           return 1;
+       }
+
+      if (*++po->po_cur == '-')
+       {
+         if (*++po->po_cur == 0)
+           {
+             /* End of options */
+             permute (po);
+             ++po->po_ind;
+             return 1;
+           }
+
+         /* It's a long option */
+         po->po_chr = 0;
+         return 0;
+       }
+    }
+
+  po->po_chr = *po->po_cur++;
+
+  return 0;
+}
+
+/* Parse options */
+static int
+parse (struct mu_parseopt *po)
+{
+  int rc;
+
+  rc = mu_list_create (&po->po_optlist);
+  if (rc)
+    return rc;
+  mu_list_set_destroy_item (po->po_optlist, mu_option_cache_destroy);
+  
+  po->po_ind = 0;
+  if (!(po->po_flags & MU_PARSEOPT_ARGV0))
+    {
+      po->po_ind++;
+      if (!(po->po_flags & MU_PARSEOPT_PROG_NAME))
+       {
+         char *p = strrchr (po->po_argv[0], '/');
+         if (p)
+           p++;
+         else
+           p = (char*) po->po_argv[0];
+         if (strlen (p) > 3 && memcmp (p, "lt-", 3) == 0)
+           p += 3;
+         po->po_prog_name = p;
+       }
+    }
+  else if (!(po->po_flags & MU_PARSEOPT_PROG_NAME))
+    po->po_prog_name = NULL;
+
+  po->po_arg_start = po->po_ind;
+  po->po_arg_count = 0;
+  po->po_permuted = 0;
+  
+  po->po_cur = "";
+
+  po->po_opterr = -1;
+  
+  while (next_opt (po) == 0)
+    {
+      struct mu_option *opt;
+      char *long_opt;
+      
+      if (po->po_chr)
+       {
+         opt = find_short_option (po, po->po_chr);
+         long_opt = NULL;
+       }
+      else
+       {
+         long_opt = po->po_cur;
+         opt = find_long_option (po, long_opt, &po->po_cur);
+       }
+
+      if (opt)
+       {
+         char *arg = NULL;
+         
+         if (opt->opt_arg)
+           {
+             if (po->po_cur[0])
+               {
+                 arg = po->po_cur;
+                 po->po_cur = "";
+               }
+             else if (opt->opt_flags & MU_OPTION_ARG_OPTIONAL)
+               /* ignore it */;
+             else if (po->po_ind < po->po_argc)
+               arg = po->po_argv[po->po_ind++];
+             else
+               {
+                 if (long_opt)
+                   parse_error (po,
+                                _("option '--%s' requires an argument"),
+                                long_opt);
+                 else
+                   parse_error (po,
+                                _("option '-%c' requires an argument"),
+                                po->po_chr);
+                 po->po_opterr = po->po_ind;
+                 if (po->po_flags & MU_PARSEOPT_NO_ERREXIT)
+                   {
+                     if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
+                       po->po_arg_count++;
+                     continue;
+                   }
+                 exit (EXIT_ERROR);
+               }       
+           }
+         else
+           {
+             if (long_opt
+                 && po->po_cur[0]
+                 && !(po->po_flags & MU_OPTION_ARG_OPTIONAL))
+               {
+                 parse_error (po,
+                              _("option '--%s' doesn't allow an argument"),
+                              long_opt);
+                 po->po_opterr = po->po_ind;
+                 if (po->po_flags & MU_PARSEOPT_NO_ERREXIT)
+                   {
+                     if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
+                       po->po_arg_count++;
+                     continue;
+                   }
+                 exit (EXIT_ERROR);
+               }
+             arg = NULL;
+           }
+         
+         add_option_cache (po, opt, arg);
+       }
+      else
+       {
+         po->po_opterr = po->po_ind;
+         if (po->po_flags & MU_PARSEOPT_NO_ERREXIT)
+           {
+             if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
+               po->po_arg_count++;
+             continue;
+           }
+         exit (EXIT_ERROR);
+       }
+    }
+
+  if (!po->po_permuted)
+    po->po_arg_start = po->po_ind - 1 - po->po_arg_count;
+  return 0;
+}
+
+/* Initialize structure mu_parseopt with given options and flags. */
+static int
+parseopt_init (struct mu_parseopt *po, struct mu_option **options,
+              int flags)
+{
+  struct mu_option *opt;
+  size_t i, j;
+
+  memset (po, 0, sizeof *po);
+  po->po_argc = 0;
+  po->po_argv = NULL;
+  po->po_optc = 0;
+  po->po_flags = flags;
+    
+  /* Fix up flags */
+  if (flags & MU_PARSEOPT_IGNORE_ERRORS)
+    flags |= MU_PARSEOPT_NO_ERREXIT;
+
+  if (!(flags & MU_PARSEOPT_PROG_DOC))
+    po->po_prog_doc = NULL;
+  if (!(flags & MU_PARSEOPT_PROG_ARGS))
+    po->po_prog_args = NULL;
+  if (!(flags & MU_PARSEOPT_BUG_ADDRESS))
+    po->po_bug_address = NULL;
+  if (!(flags & MU_PARSEOPT_PACKAGE_NAME))
+    po->po_package_name = NULL;
+  if (!(flags & MU_PARSEOPT_PACKAGE_URL))
+    po->po_package_url = NULL;
+  if (!(flags & MU_PARSEOPT_PACKAGE_URL))
+    po->po_data = NULL;
+  if (!(flags & MU_PARSEOPT_HELP_HOOK))
+    po->po_help_hook = NULL;
+  
+  /* Count the options */
+  po->po_optc = 0;
+  for (i = 0; options[i]; i++)
+    for (opt = options[i]; !MU_OPTION_IS_END (opt); opt++)
+      ++po->po_optc;
+
+  if (!(flags & MU_PARSEOPT_NO_STDOPT))
+    for (i = 0; !MU_OPTION_IS_END (&mu_default_options[i]); i++)
+      ++po->po_optc;
+  
+  /* Allocate the working buffer of option pointers */
+  po->po_optv = mu_calloc (po->po_optc + 1, sizeof (*po->po_optv));
+  if (!po->po_optv)
+    return -1;
+
+  /* Fill in the array */
+  j = 0;
+  for (i = 0; options[i]; i++)
+    for (opt = options[i]; !MU_OPTION_IS_END (opt); opt++, j++)
+      {
+       if (!opt->opt_set)
+         opt->opt_set = mu_option_set_value;
+       po->po_optv[j] = opt;
+      }
+  
+  if (!(flags & MU_PARSEOPT_NO_STDOPT))
+    for (i = 0; !MU_OPTION_IS_END (&mu_default_options[i]); i++, j++)
+      po->po_optv[j] = &mu_default_options[i];
+  
+  po->po_optv[j] = NULL;
+
+  /* Ensure sane start of options.  This is necessary, in particular,
+     because optcmp backs up until it finds an element with cleared
+     MU_OPTION_ALIAS bit. */
+  po->po_optv[0]->opt_flags &= MU_OPTION_ALIAS;
+  if (!(flags & MU_PARSEOPT_NO_SORT))
+    {
+      /* Sort the options */
+      size_t start;
+
+      for (start = 0; start < po->po_optc; )
+       {
+         if (MU_OPTION_IS_GROUP_HEADER (po->po_optv[start]))
+           start = sort_group (po->po_optv, start + 1);
+         else 
+           start = sort_group (po->po_optv, start);
+       }
+    }
+  return 0;
+}
+
+/* Parse command line from ARGC/ARGV. Valid options are given in
+   OPTIONS.  FLAGS control the parsing. */
+int
+mu_parseopt (struct mu_parseopt *po,
+            int argc, char **argv, struct mu_option **options,
+            int flags)
+{
+  int rc;
+
+  if (flags & MU_PARSEOPT_REUSE)
+    {
+      mu_list_clear (po->po_optlist);
+      po->po_flags = (po->po_flags & MU_PARSEOPT_IMMUTABLE_MASK)
+                       | (flags & ~MU_PARSEOPT_IMMUTABLE_MASK);
+    }
+  else
+    {
+      rc = parseopt_init (po, options, flags);
+      if (rc)
+       return rc;
+    }
+  po->po_argc = argc;
+  po->po_argv = argv;
+  
+  rc = parse (po);
+
+  if (rc == 0)
+    {
+      if (po->po_opterr >= 0)
+       rc = -1; 
+      else
+       {
+         if (po->po_flags & MU_PARSEOPT_IMMEDIATE)
+           rc = mu_parseopt_apply (po);
+       }
+    }
+
+  return rc;
+}
+
+void
+mu_parseopt_free (struct mu_parseopt *popt)
+{
+  free (popt->po_optv);
+  mu_list_destroy (&popt->po_optlist);
+}
+
+static int
+parseopt_apply (void *item, void *data)
+{
+  struct mu_option_cache *cp = item;
+  struct mu_parseopt *popt = data;
+  cp->cache_opt->opt_set (popt, cp->cache_opt, cp->cache_arg);
+  return 0;
+}
+
+int
+mu_parseopt_apply (struct mu_parseopt *popt)
+{
+  return mu_list_foreach (popt->po_optlist, parseopt_apply, popt);
+}
+
+void
+mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
+                    char const *arg)
+{
+  if (opt->opt_ptr)
+    {
+      char *errmsg;
+      int rc;
+      
+      if (arg == NULL)
+       {
+         if (opt->opt_arg == NULL)
+           arg = "1";
+         else
+           {
+             *(void**)opt->opt_ptr = NULL;
+             return;
+           }
+       }
+      rc = mu_str_to_c (arg, opt->opt_type, opt->opt_ptr, &errmsg);
+      if (rc)
+       {
+         char const *errtext;
+         if (errmsg)
+           errtext = errmsg;
+         else
+           errtext = mu_strerror (rc);
+
+         if (opt->opt_long)
+           parse_error (po, "--%s: %s", opt->opt_long, errtext);
+         else
+           parse_error (po, "-%c: %s", opt->opt_short, errtext);
+         free (errmsg);
+
+         if (!(po->po_flags & MU_PARSEOPT_NO_ERREXIT))
+           exit (EXIT_ERROR);
+       }
+    }
+}
diff --git a/libmu_cfg/virtdomain.c b/libmailutils/opt/progname.c
similarity index 57%
copy from libmu_cfg/virtdomain.c
copy to libmailutils/opt/progname.c
index c2dc2cc..19d430e 100644
--- a/libmu_cfg/virtdomain.c
+++ b/libmailutils/opt/progname.c
@@ -1,6 +1,5 @@
-/* This file is part of GNU Mailutils
-   Copyright (C) 2007, 2010-2012, 2014-2016 Free Software Foundation,
-   Inc.
+/* help.c -- 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
@@ -15,22 +14,32 @@
    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/libcfg.h"
+#include <string.h>
+#include <mailutils/alloc.h>
+#include <mailutils/opt.h>
 
-static struct mu_gocs_virtual virtdomain_settings;
+char *mu_progname;
+char *mu_absprogname;
 
-static struct mu_cfg_param mu_virtdomain_param[] = {
-  { "passwd-dir", mu_cfg_string, &virtdomain_settings, 0, NULL,
-    N_("Name of the directory where virtual domain password files are "
-       "located."),
-    N_("dir") },
-  { NULL }
-};
+void
+mu_set_progname (char const *arg)
+{
+  char *p;
 
-DCL_CFG_CAPA (virtdomain);
-     
+  free (mu_absprogname);
+  mu_absprogname = mu_strdup (arg);
+  
+  p = strrchr (arg, '/');
+  if (p)
+    ++p;
+  else
+    p = (char*) arg;
+  if (strlen (p) > 3 && memcmp (p, "lt-", 3) == 0)
+    p += 3;
+  free (mu_progname);
+  mu_progname = mu_strdup (p);
+}
diff --git a/libmailutils/server/msrv.c b/libmailutils/server/msrv.c
index 3ef1f78..a60fd53 100644
--- a/libmailutils/server/msrv.c
+++ b/libmailutils/server/msrv.c
@@ -890,24 +890,24 @@ _cb_port (void *data, mu_config_value_t *val)
 }
 
 static struct mu_cfg_param dot_server_cfg_param[] = {
-  { "max-children", mu_cfg_size,
+  { "max-children", mu_c_size,
     NULL, mu_offsetof (struct _mu_m_server,max_children), NULL,
     N_("Maximum number of children processes to run simultaneously.") },
   { "mode", mu_cfg_callback,
     NULL, mu_offsetof (struct _mu_m_server,mode), _cb_daemon_mode,
     N_("Set daemon mode (either inetd (or interactive) or daemon)."),
     N_("mode") },
-  { "foreground", mu_cfg_bool,
+  { "foreground", mu_c_bool,
     NULL, mu_offsetof (struct _mu_m_server, foreground), NULL,
     N_("Run in foreground.") },
-  { "pidfile", mu_cfg_string,
+  { "pidfile", mu_c_string,
     NULL, mu_offsetof (struct _mu_m_server,pidfile), NULL,
     N_("Store PID of the master process in this file."),
     N_("file") },
   { "port", mu_cfg_callback,
     NULL, mu_offsetof (struct _mu_m_server, hints), _cb_port,
     N_("Default port number.") },
-  { "timeout", mu_cfg_time,
+  { "timeout", mu_c_time,
     NULL, mu_offsetof (struct _mu_m_server,timeout), NULL,
     N_("Set idle timeout.") },
   { "server", mu_cfg_section, NULL, 0, NULL,
@@ -918,13 +918,13 @@ static struct mu_cfg_param dot_server_cfg_param[] = {
 };
     
 static struct mu_cfg_param server_cfg_param[] = {
-  { "single-process", mu_cfg_bool, 
+  { "single-process", mu_c_bool, 
     NULL, mu_offsetof (struct mu_srv_config, single_process), NULL,
     N_("Do not spawn sub-process to handle requests in this server.") },
-  { "transcript", mu_cfg_bool,
+  { "transcript", mu_c_bool,
     NULL, mu_offsetof (struct mu_srv_config, transcript), NULL,
     N_("Log the session transcript.") },
-  { "timeout", mu_cfg_time,
+  { "timeout", mu_c_time,
     NULL, mu_offsetof (struct mu_srv_config, timeout), NULL,
     N_("Set idle timeout.") },
   { "acl", mu_cfg_section,
diff --git a/libmailutils/string/Makefile.am b/libmailutils/string/Makefile.am
index a9fbd56..47e578e 100644
--- a/libmailutils/string/Makefile.am
+++ b/libmailutils/string/Makefile.am
@@ -25,6 +25,7 @@ libstring_la_SOURCES = \
  cstrupper.c\
  hexstr.c\
  stpcpy.c\
+ str_to_c.c\
  strltrim.c\
  strskip.c\
  stripws.c\
@@ -40,4 +41,6 @@ libstring_la_SOURCES = \
  wordsplit.c\
  xdecode.c
 
-AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
+EXTRA_DIST=to_sn.c to_un.c
+
+AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils -I${srcdir}
diff --git a/libmailutils/string/str_to_c.c b/libmailutils/string/str_to_c.c
new file mode 100644
index 0000000..4a3b23b
--- /dev/null
+++ b/libmailutils/string/str_to_c.c
@@ -0,0 +1,295 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General
+   Public License along with this library.  If not, see 
+   <http://www.gnu.org/licenses/>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+#include <mailutils/cidr.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/util.h>
+#include <mailutils/alloc.h>
+#include <mailutils/cctype.h>
+#include <mailutils/io.h>
+#include <mailutils/nls.h>
+
+typedef int (*str_to_c_t) (void *tgt, char const *string, char **errmsg);
+
+static int
+to_string (void *tgt, char const *string, char **errmsg)
+{
+  char **cptr = tgt;
+  if (string)
+    {
+      *cptr = mu_strdup (string);
+      if (!*cptr)
+       return errno;
+    }
+  else
+    *cptr = NULL;
+  return 0;
+}
+
+#define STR_TO_FUN to_short
+#define STR_TO_TYPE signed short
+#define STR_TO_MIN SHRT_MIN
+#define STR_TO_MAX SHRT_MAX
+#include "to_sn.c"
+
+#define STR_TO_FUN to_ushort
+#define STR_TO_TYPE unsigned short
+#define STR_TO_MAX USHRT_MAX
+#include "to_un.c"
+
+#define STR_TO_FUN to_int
+#define STR_TO_TYPE signed int
+#define STR_TO_MIN INT_MIN
+#define STR_TO_MAX INT_MAX
+#include "to_sn.c"
+
+#define STR_TO_FUN to_uint
+#define STR_TO_TYPE unsigned int
+#define STR_TO_MAX UINT_MAX
+#include "to_un.c"
+
+#define STR_TO_FUN to_long
+#define STR_TO_TYPE signed long
+#define STR_TO_MIN LONG_MIN
+#define STR_TO_MAX LONG_MAX
+#include "to_sn.c"
+
+#define STR_TO_FUN to_ulong
+#define STR_TO_TYPE unsigned long
+#define STR_TO_MAX ULONG_MAX
+#include "to_un.c"
+
+#define STR_TO_FUN to_size_t
+#define STR_TO_TYPE size_t
+#define STR_TO_MAX ((size_t)-1)
+#include "to_un.c"
+
+static int
+time_multiplier (const char *str, unsigned *m, unsigned *plen)
+{
+  static struct timetab
+  {
+    char *name;
+    unsigned mul;
+  } tab[] = {
+    { "seconds", 1 },
+    { "minutes", 60 },
+    { "hours", 60*60 },
+    { "days",  24*60*60 },
+    { "weeks", 7*24*60*60 },
+    { "months", 31*7*24*60*60 },
+    { NULL }
+  };
+  struct timetab *p;
+  int slen;
+
+  for (slen = 0; str[slen]; slen++)
+    if (mu_isspace (str[slen]))
+      break;
+
+  for (p = tab; p->name; p++)
+    {
+      if (p->name[0] == mu_tolower (str[0]))
+       {
+         int nlen = strlen (p->name);
+
+         if (nlen > slen)
+           nlen = slen;
+                       
+         if (strncasecmp (p->name, str, nlen) == 0) {
+           *m = p->mul;
+           if (plen)
+             *plen = nlen;
+           return 0;
+         }
+       }
+    }
+  return 1;
+}
+
+static int
+to_time_t (void *tgt, char const *string, char **errmsg)
+{
+  time_t *ptr = tgt;
+  int rc = 0;
+  time_t interval = 0;
+
+  while (*string)
+    {
+      char *p;
+      unsigned long n;
+      unsigned mul, len;
+
+      while (*string && mu_isspace (*string))
+       string++;
+
+      if (!mu_isdigit (*string) && time_multiplier (string, &mul, &len) == 0)
+       {
+         n = 1;
+         string += len;
+       }
+      else
+       {
+         n = strtoul (string, &p, 10);
+         if (*p && !mu_isspace (*p))
+           {
+             string = p;
+             rc = 1;
+             break;
+           }
+         
+         while (*p && mu_isspace (*p))
+           p++;
+
+         string = p;
+         if (*string)
+           {
+             if ((rc = time_multiplier (string, &mul, &len)))
+               break;
+             string += len;
+           }
+         else
+           mul = 1;
+       }
+      interval += n * mul;
+    }
+
+  if (rc)
+    {
+      if (errmsg)
+       mu_asprintf (errmsg, _("invalid time specification near %s"), string);
+      return EINVAL;
+    }
+  
+  *ptr = interval;
+  return 0;
+}
+  
+static int
+to_bool (void *tgt, char const *string, char **errmsg)
+{
+  int *ptr = tgt;
+  
+  if (strcmp (string, "yes") == 0
+      || strcmp (string, "on") == 0
+      || strcmp (string, "t") == 0
+      || strcmp (string, "true") == 0
+      || strcmp (string, "1") == 0)
+    *ptr = 1;
+  else if (strcmp (string, "no") == 0
+          || strcmp (string, "off") == 0
+          || strcmp (string, "nil") == 0
+          || strcmp (string, "false") == 0
+          || strcmp (string, "0") == 0)
+    *ptr = 0;
+  else
+    return EINVAL;
+  
+  return 0;
+}
+
+#if 0
+static int
+to_ipv4 (void *tgt, char const *string, char **errmsg)
+{
+  struct in_addr *ptr = tgt;
+  struct in_addr addr;
+  
+  if (inet_aton (string, &addr) == 0)
+    {
+      mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus, _("not an IPv4"));
+      mu_cfg_error_count++;
+      return 1;
+    }
+  addr.s_addr = ntohl (addr.s_addr);
+
+  *ptr = addr;
+  return 0;
+}
+#endif
+
+static int
+to_cidr (void *tgt, char const *string, char **errmsg)
+{
+  struct mu_cidr *ptr = tgt;
+  return mu_cidr_from_string (ptr, string);
+}
+
+static int
+to_incr (void *tgt, char const *string, char **errmsg)
+{
+  ++*(int*)tgt;
+  return 0;
+}
+
+static str_to_c_t str_to_c[] = {
+  [mu_c_string] = to_string, 
+  [mu_c_short]  = to_short,  
+  [mu_c_ushort] = to_ushort, 
+  [mu_c_int]    = to_int,    
+  [mu_c_uint]   = to_uint,   
+  [mu_c_long]   = to_long,   
+  [mu_c_ulong]  = to_ulong,  
+  [mu_c_size]   = to_size_t,   
+  /* FIXME  [mu_c_off]    = { to_off,    generic_dealloc }, */
+  [mu_c_time]   = to_time_t, 
+  [mu_c_bool]   = to_bool,
+  /* FIXME [mu_c_ipv4]   = to_ipv4, */
+  [mu_c_cidr]   = to_cidr,
+  /* FIXME  [mu_c_host]   = { to_host,   generic_dealloc } */
+  [mu_c_incr]   = to_incr
+};
+
+char const *mu_c_type_str[] = {
+  [mu_c_string]  = "mu_c_string",
+  [mu_c_short]   = "mu_c_short",  
+  [mu_c_ushort]  = "mu_c_ushort", 
+  [mu_c_int]     = "mu_c_int",    
+  [mu_c_uint]    = "mu_c_uint",   
+  [mu_c_long]    = "mu_c_long",   
+  [mu_c_ulong]   = "mu_c_ulong",  
+  [mu_c_size]    = "mu_c_size",   
+  [mu_c_off]     = "mu_c_off",    
+  [mu_c_time]    = "mu_c_time",   
+  [mu_c_bool]    = "mu_c_bool",   
+  [mu_c_ipv4]    = "mu_c_ipv4",   
+  [mu_c_cidr]    = "mu_c_cidr",   
+  [mu_c_host]    = "mu_c_host",   
+  [mu_c_incr]    = "mu_c_incr",   
+  [mu_c_void]    = "mu_c_void"
+};
+
+int
+mu_str_to_c (char const *string, enum mu_c_type type, void *tgt, char **errmsg)
+{
+  if (errmsg)
+    *errmsg = NULL;
+  if ((size_t)type >= sizeof (str_to_c) / sizeof (str_to_c[0]))
+    return EINVAL;
+  if (!str_to_c[type])
+    return ENOSYS;
+  return str_to_c[type] (tgt, string, errmsg);
+}
diff --git a/libmailutils/string/to_sn.c b/libmailutils/string/to_sn.c
new file mode 100644
index 0000000..f3cbfec
--- /dev/null
+++ b/libmailutils/string/to_sn.c
@@ -0,0 +1,37 @@
+#ifndef STR_TO_FUN
+# error "STR_TO_FUN not defined"
+#endif
+#ifndef STR_TO_TYPE
+# error "STR_TO_TYPE not defined"
+#endif
+#ifndef STR_TO_MIN
+# error "STR_TO_MIN not defined"
+#endif
+#ifndef STR_TO_MAX
+# error "STR_TO_MAX not defined"
+#endif
+
+static int
+STR_TO_FUN (void *tgt, char const *string, char **errmsg)
+{
+  STR_TO_TYPE *ptr = tgt;
+  intmax_t v;
+  char *p;
+  
+  errno = 0;
+  v = strtoimax (string, &p, 10);
+  if (errno)
+    return errno;
+  if (*p)
+    return EINVAL;
+  if (STR_TO_MIN <= v && v <= STR_TO_MAX)
+    {
+      *ptr = (STR_TO_TYPE) v;
+      return 0;
+    }
+  return ERANGE;
+}
+#undef STR_TO_FUN
+#undef STR_TO_TYPE
+#undef STR_TO_MIN
+#undef STR_TO_MAX
diff --git a/libmailutils/string/to_un.c b/libmailutils/string/to_un.c
new file mode 100644
index 0000000..b6878c0
--- /dev/null
+++ b/libmailutils/string/to_un.c
@@ -0,0 +1,34 @@
+#ifndef STR_TO_FUN
+# error "STR_TO_FUN not defined"
+#endif
+#ifndef STR_TO_TYPE
+# error "STR_TO_TYPE not defined"
+#endif
+#ifndef STR_TO_MAX
+# error "STR_TO_MAX not defined"
+#endif
+
+static int
+STR_TO_FUN (void *tgt, char const *string, char **errmsg)
+{
+  STR_TO_TYPE *ptr = tgt;
+  uintmax_t v;
+  char *p;
+  
+  errno = 0;
+  v = strtoumax (string, &p, 10);
+  if (errno)
+    return errno;
+  if (*p)
+    return EINVAL;
+  if (v <= STR_TO_MAX)
+    {
+      *ptr = (STR_TO_TYPE) v;
+      return 0;
+    }
+  return ERANGE;
+}
+
+#undef STR_TO_FUN
+#undef STR_TO_TYPE
+#undef STR_TO_MAX
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index fe72adf..51e4e68 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -20,11 +20,13 @@ mailcap
 mimehdr
 modtofsaf
 msgset
+parseopt
 prop
 scantime
 strftime
 strin
 strout
+strtoc
 tempfile
 url-comp
 url-parse
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 699d496..5655d80 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -56,11 +56,13 @@ noinst_PROGRAMS = \
  modtofsaf\
  msgset\
  modmesg\
+ parseopt\
  prop\
  scantime\
  strftime\
  strin\
  strout\
+ strtoc\
  tempfile\
  url-comp\
  url-parse\
@@ -102,12 +104,36 @@ TESTSUITE_AT = \
  modmesg03.at\
  modtofsaf.at\
  msgset.at\
+ parseopt00.at\
+ parseopt01.at\
+ parseopt02.at\
+ parseopt03.at\
+ parseopt04.at\
+ parseopt05.at\
+ parseopt06.at\
+ parseopt07.at\
+ parseopt08.at\
+ parseopt09.at\
+ parseopt10.at\
+ parseopt11.at\
+ parseopt12.at\
+ parseopt13.at\
+ parseopt14.at\
+ parseopt15.at\
+ parseopt16.at\
+ parseopt17.at\
+ parseopt18.at\
+ parseopt19.at\
+ parseopt20.at\
+ parseopt21.at\
+ parseopt22.at\
  prop.at\
  scantime.at\
  strftime.at\
  strerr.at\
  strin.at\
  strout.at\
+ strtoc.at\
  testsuite.at\
  url.at\
  url-comp.at\
diff --git a/libmailutils/tests/parseopt.c b/libmailutils/tests/parseopt.c
new file mode 100644
index 0000000..d3caf65
--- /dev/null
+++ b/libmailutils/tests/parseopt.c
@@ -0,0 +1,118 @@
+/* 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/opt.h>
+
+char *file_name;
+char *opt_value = "initial";
+char *find_value;
+int jobs = 0;
+int x_option;
+int a_option;
+int d_option;
+
+struct mu_option group_a[] = {
+  MU_OPTION_GROUP("Group A"),
+  { "file", 'f', "FILE", MU_OPTION_DEFAULT,
+    "set file name",
+    mu_c_string, &file_name
+  },
+  { "optional", 'o', "FILE", MU_OPTION_ARG_OPTIONAL,
+    "optional argument",
+    mu_c_string, &opt_value },
+  { NULL, 'x', NULL, MU_OPTION_DEFAULT,
+    "short-only option",
+    mu_c_incr, &x_option },
+  { "all", 'a', NULL, MU_OPTION_DEFAULT,
+    "no arguments to this one",
+    mu_c_bool, &a_option },
+  MU_OPTION_END
+};
+
+struct mu_option group_b[] = {
+  MU_OPTION_GROUP("Group B"),
+  { "debug", 'd', NULL, MU_OPTION_DEFAULT,
+    "another option",
+    mu_c_incr, &d_option },
+  { "verbose", 'v', NULL, MU_OPTION_ALIAS },
+  { "find", 'F', "VALUE", MU_OPTION_DEFAULT,
+    "find VALUE",
+    mu_c_string, &find_value },
+  { "jobs", 'j', "N", MU_OPTION_DEFAULT,
+    "sets numeric value",
+    mu_c_int, &jobs },
+  MU_OPTION_END
+};
+
+struct mu_option *optv[] = { group_a, group_b, NULL };
+
+#define S(s) ((s)?(s):"(null)")
+
+int
+main (int argc, char *argv[])
+{
+  struct mu_parseopt po;
+  int rc;
+  int i;
+  int flags = MU_PARSEOPT_DEFAULT;
+  
+  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+
+  if (getenv ("MU_PARSEOPT_DEFAULT"))
+    flags = MU_PARSEOPT_DEFAULT;
+  else
+    {
+      if (getenv ("MU_PARSEOPT_IN_ORDER"))
+       flags |= MU_PARSEOPT_IN_ORDER;
+      if (getenv ("MU_PARSEOPT_IGNORE_ERRORS"))
+       flags |= MU_PARSEOPT_IGNORE_ERRORS;
+      if (getenv ("MU_PARSEOPT_IN_ORDER"))
+       flags |= MU_PARSEOPT_IN_ORDER;
+      if (getenv ("MU_PARSEOPT_NO_ERREXIT"))
+       flags |= MU_PARSEOPT_NO_ERREXIT;
+      if (getenv ("MU_PARSEOPT_NO_STDOPT"))
+       flags |= MU_PARSEOPT_NO_STDOPT;
+    }
+  
+  rc = mu_parseopt (&po, argc, argv, optv, flags);
+  printf ("rc=%d\n", rc);
+  mu_parseopt_apply (&po);
+
+  argc -= po.po_arg_start;
+  argv += po.po_arg_start;
+
+  mu_parseopt_free (&po);
+
+  printf ("file_name=%s\n", S(file_name));
+  printf ("opt_value=%s\n", S(opt_value));
+  printf ("x_option=%d\n", x_option);
+  printf ("a_option=%d\n", a_option);
+  printf ("find_value=%s\n", S(find_value));
+  printf ("d_option=%d\n", d_option);
+  printf ("jobs=%d\n", jobs);
+  
+  printf ("argv:\n");
+  for (i = 0; i < argc; i++)
+    {
+      printf ("%d: %s\n", i, argv[i]);
+    }
+
+  return 0;
+}
diff --git a/libmailutils/tests/strout.at b/libmailutils/tests/parseopt00.at
similarity index 73%
copy from libmailutils/tests/strout.at
copy to libmailutils/tests/parseopt00.at
index b71219d..245b637 100644
--- a/libmailutils/tests/strout.at
+++ b/libmailutils/tests/parseopt00.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,23 +14,21 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strout])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([empty command line])
+AT_KEYWORDS([parseopt parseopt00])
 AT_CHECK([
-strout now is the time for all good men
+MU_PARSEOPT_DEFAULT=1
+parseopt
 ],
 [0],
-[now
-is
-the
-time
-for
-all
-good
-men
+[rc=0
+file_name=(null)
+opt_value=initial
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
 ])
-
 AT_CLEANUP
-
-
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/parseopt01.at
similarity index 68%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/parseopt01.at
index c100777..ca9517d 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/parseopt01.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,24 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([command line without options])
+AT_KEYWORDS([parseopt parseopt_noopt parseopt01])
 AT_CHECK([
-strout -err now is the time for all good men
+MU_PARSEOPT_DEFAULT=1
+parseopt command line arguments
 ],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[rc=0
+file_name=(null)
+opt_value=initial
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
-
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/parseopt02.at
similarity index 68%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/parseopt02.at
index c100777..fb91d53 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/parseopt02.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,24 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([short options])
+AT_KEYWORDS([parseopt parseopt_short parseopt02])
 AT_CHECK([
-strout -err now is the time for all good men
+MU_PARSEOPT_DEFAULT=1
+parseopt -f file -x -a -d command line arguments
 ],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[rc=0
+file_name=file
+opt_value=initial
+x_option=1
+a_option=1
+find_value=(null)
+d_option=1
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt03.at
similarity index 66%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt03.at
index 053c741..08d2cfc 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt03.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([short option with argument])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_arg parseopt03])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt -ffile -x -a -d command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=file
+opt_value=initial
+x_option=1
+a_option=1
+find_value=(null)
+d_option=1
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt04.at
similarity index 65%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt04.at
index 053c741..319b196 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt04.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([short option with optional argument])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_opt_arg parseopt04])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt -ofile command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=(null)
+opt_value=file
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt05.at
similarity index 65%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt05.at
index 053c741..830ddbb 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt05.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([short option without optional argument])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_opt_noarg parseopt05])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt -o command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=(null)
+opt_value=(null)
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt06.at
similarity index 66%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt06.at
index 053c741..87bdfbe 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt06.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([incremental short option])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_incr parseopt06])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt -d -d command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=(null)
+opt_value=initial
+x_option=0
+a_option=0
+find_value=(null)
+d_option=2
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt07.at
similarity index 66%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt07.at
index 053c741..ae0fbb3 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt07.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([short option clustering])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_cluster parseopt07])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt -xffile -dado10 command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=file
+opt_value=10
+x_option=1
+a_option=1
+find_value=(null)
+d_option=2
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/parseopt08.at
similarity index 68%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/parseopt08.at
index c100777..0b020f1 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/parseopt08.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,24 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([long options])
+AT_KEYWORDS([parseopt parseopt_long parseopt08])
 AT_CHECK([
-strout -err now is the time for all good men
+MU_PARSEOPT_DEFAULT=1
+parseopt --file=file --all command line arguments
 ],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[rc=0
+file_name=file
+opt_value=initial
+x_option=0
+a_option=1
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt09.at
similarity index 66%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt09.at
index 053c741..7f6ca10 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt09.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([long option with argument])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_arg parseopt09])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt --file file command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=file
+opt_value=initial
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt10.at
similarity index 65%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt10.at
index 053c741..dbd0d42 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt10.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([long option with optional argument])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_opt_arg parseopt10])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt --optional=file command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=(null)
+opt_value=file
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt11.at
similarity index 65%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt11.at
index 053c741..5284e52 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt11.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([long option without optional argument])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_opt_noarg parseopt11])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt --optional command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=(null)
+opt_value=(null)
+x_option=0
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt12.at
similarity index 66%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt12.at
index 053c741..a8d56ca 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt12.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([incremental long option])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_incr parseopt12])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt --debug --debug command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=(null)
+opt_value=initial
+x_option=0
+a_option=0
+find_value=(null)
+d_option=2
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt13.at
similarity index 66%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt13.at
index 053c741..d67865f 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt13.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([abbreviated long options])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_abbr parseopt13])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt --fil=file --fin=Word command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=file
+opt_value=initial
+x_option=0
+a_option=0
+find_value=Word
+d_option=0
+jobs=0
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/parseopt14.at
similarity index 68%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/parseopt14.at
index c100777..a06e425 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/parseopt14.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,24 +14,16 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([ambiguous abbreviated long options])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_abbr parseopt_long_ambig 
parseopt14])
 AT_CHECK([
-strout -err now is the time for all good men
+MU_PARSEOPT_DEFAULT=1
+parseopt --fi=file --fi=Word command line arguments
 ],
-[0],
+[1],
 [],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[parseopt: option '--fi' is ambiguous; possibilities:
+--file
+--find
 ])
-
 AT_CLEANUP
-
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt15.at
similarity index 64%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt15.at
index 053c741..5c51090 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt15.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([mixed long and short options])
+AT_KEYWORDS([parseopt parseopt_long parseopt_short parseopt15.at])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+MU_PARSEOPT_DEFAULT=1
+parseopt --file=filename -o -xa --find word -j10 command line arguments
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=filename
+opt_value=(null)
+x_option=1
+a_option=1
+find_value=word
+d_option=0
+jobs=10
+argv:
+0: command
+1: line
+2: arguments
 ])
-
 AT_CLEANUP
-
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/parseopt16.at
similarity index 72%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/parseopt16.at
index c100777..af13145 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/parseopt16.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,24 +14,20 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([option aliases])
+AT_KEYWORDS([parseopt parseopt_long parseopt_short parseopt16.at])
 AT_CHECK([
-strout -err now is the time for all good men
+parseopt -vvv
 ],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[rc=0
+file_name=(null)
+opt_value=initial
+x_option=0
+a_option=0
+find_value=(null)
+d_option=3
+jobs=0
+argv:
 ])
-
 AT_CLEANUP
-
-
diff --git a/imap4d/tests/create01.at b/libmailutils/tests/parseopt17.at
similarity index 67%
copy from imap4d/tests/create01.at
copy to libmailutils/tests/parseopt17.at
index 02bf259..b82df13 100644
--- a/imap4d/tests/create01.at
+++ b/libmailutils/tests/parseopt17.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create])
-AT_KEYWORDS([create create00])
-
+AT_SETUP([argument permutation])
+AT_KEYWORDS([parseopt parseopt_long parseopt_short parseopt17.at])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create flat
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name flat
+parseopt more --file=file arguments follow -x -o options
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./flat
+[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/strerr.at b/libmailutils/tests/parseopt18.at
similarity index 67%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/parseopt18.at
index c100777..e9f753a 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/parseopt18.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,24 +14,24 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([double-dash])
+AT_KEYWORDS([parseopt parseopt_long parseopt_short parseopt_double_dash 
parseopt18.at])
 AT_CHECK([
-strout -err now is the time for all good men
+parseopt -x --file=foobar -- -a --optional arg
 ],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[rc=0
+file_name=foobar
+opt_value=initial
+x_option=1
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: -a
+1: --optional
+2: arg
 ])
-
 AT_CLEANUP
 
-
diff --git a/imap4d/tests/create02.at b/libmailutils/tests/parseopt19.at
similarity index 65%
copy from imap4d/tests/create02.at
copy to libmailutils/tests/parseopt19.at
index 053c741..94a59f7 100644
--- a/imap4d/tests/create02.at
+++ b/libmailutils/tests/parseopt19.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,25 +14,25 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([create nested])
-AT_KEYWORDS([create create01])
-
+AT_SETUP([double-dash with permutation])
+AT_KEYWORDS([parseopt parseopt_long parseopt_short parseopt_double_dash 
parseopt19.at])
 AT_CHECK([
-AT_DATA([input],[dnl
-1 create en/to/tre
-X LOGOUT
-])
-
-imap4d IMAP4D_OPTIONS < input | tr -d '\r'
-find . -name tre
+parseopt -x more --file=foobar -- -a --optional arg
 ],
 [0],
-[* PREAUTH IMAP4rev1 Test mode
-1 OK CREATE Completed
-* BYE Session terminating.
-X OK LOGOUT Completed
-./en/to/tre
+[rc=0
+file_name=foobar
+opt_value=initial
+x_option=1
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: more
+1: -a
+2: --optional
+3: arg
 ])
-
 AT_CLEANUP
 
diff --git a/libmailutils/tests/strout.at b/libmailutils/tests/parseopt20.at
similarity index 73%
copy from libmailutils/tests/strout.at
copy to libmailutils/tests/parseopt20.at
index b71219d..092a8db 100644
--- a/libmailutils/tests/strout.at
+++ b/libmailutils/tests/parseopt20.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,23 +14,13 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strout])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([short option without required argument])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_noarg parseopt20])
 AT_CHECK([
-strout now is the time for all good men
+parseopt -f
 ],
-[0],
-[now
-is
-the
-time
-for
-all
-good
-men
+[1],
+[],
+[parseopt: option '-f' requires an argument
 ])
-
-AT_CLEANUP
-
-
+AT_CLEANUP
\ No newline at end of file
diff --git a/testsuite/lstuid00.at b/libmailutils/tests/parseopt21.at
similarity index 73%
copy from testsuite/lstuid00.at
copy to libmailutils/tests/parseopt21.at
index 763743f..5982013 100644
--- a/testsuite/lstuid00.at
+++ b/libmailutils/tests/parseopt21.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,18 +14,13 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([Assigning UIDs])
-
+AT_SETUP([long option without required argument])
+AT_KEYWORDS([parseopt parseopt_long parseopt_long_noarg parseopt21])
 AT_CHECK([
-MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1)
-lstuid mbox:mbox1
+parseopt --file
 ],
-[0],
-[1: 1
-2: 2
-3: 3
-4: 4
-5: 5
+[1],
+[],
+[parseopt: option '--file' requires an argument
 ])
-
 AT_CLEANUP
\ No newline at end of file
diff --git a/libmailutils/tests/strout.at b/libmailutils/tests/parseopt22.at
similarity index 75%
copy from libmailutils/tests/strout.at
copy to libmailutils/tests/parseopt22.at
index b71219d..d07f1d5 100644
--- a/libmailutils/tests/strout.at
+++ b/libmailutils/tests/parseopt22.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2011-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,23 +14,13 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strout])
-AT_KEYWORDS([stdstream])
-
+AT_SETUP([unrecognized option])
+AT_KEYWORDS([parseopt parseopt_short parseopt_short_unrecognized parseopt22])
 AT_CHECK([
-strout now is the time for all good men
+parseopt -X
 ],
-[0],
-[now
-is
-the
-time
-for
-all
-good
-men
+[1],
+[],
+[parseopt: unrecognized option '-X'
 ])
-
-AT_CLEANUP
-
-
+AT_CLEANUP
\ No newline at end of file
diff --git a/mail/tests/version.at b/libmailutils/tests/strtoc.at
similarity index 85%
copy from mail/tests/version.at
copy to libmailutils/tests/strtoc.at
index a2367ab..583f05d 100644
--- a/mail/tests/version.at
+++ b/libmailutils/tests/strtoc.at
@@ -1,5 +1,5 @@
 # This file is part of GNU Mailutils. -*- Autotest -*-
-# Copyright (C) 2007-2012, 2014-2016 Free Software Foundation, Inc.
+# 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
@@ -14,6 +14,6 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-dnl m4_include([testsuite.inc])
-
-MUT_VERSION(mail)
+AT_SETUP([mu_str_to_c])
+AT_CHECK([strtoc])
+AT_CLEANUP
diff --git a/libmailutils/tests/strtoc.c b/libmailutils/tests/strtoc.c
new file mode 100644
index 0000000..64c3cb4
--- /dev/null
+++ b/libmailutils/tests/strtoc.c
@@ -0,0 +1,354 @@
+/* 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/>. */
+
+#include <mailutils/mailutils.h>
+
+union value
+{
+  char *v_string;
+  signed short v_short;
+  unsigned short v_ushort;
+  int v_int;
+  unsigned v_uint;
+  long v_long;
+  unsigned long v_ulong;
+  size_t v_size;
+  time_t v_time;
+  struct mu_cidr v_cidr;
+};
+
+struct value_handler
+{
+  void (*format) (union value *, FILE *);
+  int (*compare) (union value *, union value *);
+};
+
+static void
+v_string_format (union value *val, FILE *fp)
+{
+  char *p;
+       
+  fputc ('"', fp);
+  for (p = val->v_string; *p; p++)
+    {
+      if (*p == '\\' || *p == '"')
+       fputc ('\\', fp);
+      fputc (*p, fp);
+    }
+  fputc ('"', fp);
+}
+  
+static int
+v_string_compare (union value *a, union value *b)
+{
+  return strcmp (a->v_string, b->v_string);
+}
+
+static void
+v_short_format (union value *val, FILE *fp)
+{
+  fprintf (fp, "%hd", val->v_short); 
+}
+
+static int
+v_short_compare (union value *a, union value *b)
+{
+  return a->v_short != b->v_short;
+}
+
+static void
+v_ushort_format (union value *val, FILE *fp)
+{
+  fprintf (fp, "%hu", val->v_short);
+}
+
+static int
+v_ushort_compare (union value *a, union value *b)
+{
+  return a->v_ushort != b->v_ushort;
+}
+
+static void
+v_int_format (union value *val, FILE *fp)
+{
+  fprintf (fp, "%d", val->v_int);  
+}
+
+static int
+v_int_compare (union value *a, union value *b)
+{
+  return a->v_int != b->v_int;
+}
+
+static void
+v_uint_format (union value *val, FILE *fp)
+{
+  fprintf (fp, "%u", val->v_uint);
+}
+
+static int
+v_uint_compare (union value *a, union value *b)
+{
+  return a->v_uint != b->v_uint;
+}
+
+static void
+v_long_format (union value *val, FILE *fp)
+{
+  fprintf (fp, "%ld", val->v_long);  
+}
+
+static int
+v_long_compare (union value *a, union value *b)
+{
+  return a->v_long != b->v_long;
+}
+
+static void
+v_ulong_format (union value *val, FILE *fp)
+{
+  fprintf (fp, "%lu", val->v_long);  
+}
+
+static int
+v_ulong_compare (union value *a, union value *b)
+{
+  return a->v_ulong != b->v_ulong;
+}
+
+static void
+v_size_format (union value *val, FILE *fp)
+{
+  size_t v = val->v_size;
+  char buf[80];
+  size_t buflen = 80;
+  char *p = buf + buflen;
+  *--p = 0;
+  do
+    {
+      int n = v % 10;
+      *--p = n + '0';
+      v /= 10;
+    }
+  while (v && p > buf);
+
+  if (v)
+    fputs ("[overflow]", fp);
+  else
+    fputs (p, fp);
+}
+
+static int
+v_size_compare (union value *a, union value *b)
+{
+  return a->v_size != b->v_size;
+}
+
+static void
+v_cidr_format (union value *val, FILE *fp)
+{  
+  char *buf;
+
+  mu_cidr_format (&val->v_cidr, 0, &buf);
+  fprintf (fp, "%s", buf);
+  free (buf);
+}
+
+static int
+v_cidr_compare (union value *a, union value *b)
+{
+  if (a->v_cidr.family != b->v_cidr.family)
+    return 1;
+  if (a->v_cidr.len != b->v_cidr.len)
+    return 1;
+  if (memcmp (a->v_cidr.address, b->v_cidr.address, a->v_cidr.len))
+    return 1;
+  if (memcmp (a->v_cidr.netmask, b->v_cidr.netmask, a->v_cidr.len))
+    return 1;
+  return 0;
+}
+
+struct value_handler value_handler[] = {
+  [mu_c_string] = { v_string_format, v_string_compare },
+  [mu_c_short]  = { v_short_format, v_short_compare },
+  [mu_c_ushort] = { v_ushort_format, v_ushort_compare },
+  [mu_c_int]    = { v_int_format, v_int_compare },
+  [mu_c_uint]   = { v_uint_format, v_uint_compare },
+  [mu_c_long]   = { v_long_format, v_long_compare },
+  [mu_c_ulong]  = { v_ulong_format, v_ulong_compare },
+  [mu_c_size]   = { v_size_format, v_size_compare },
+#if 0
+    mu_c_time,
+#endif
+  [mu_c_bool]   = { v_int_format, v_int_compare },
+  [mu_c_cidr]   = { v_cidr_format, v_cidr_compare },
+  [mu_c_incr]   = { v_int_format, v_int_compare },
+};
+
+int
+valcmp (mu_c_type_t type, union value *a, union value *b)
+{
+  if ((size_t)type < sizeof (value_handler) / sizeof (value_handler[0])
+      && value_handler[type].compare)
+    return value_handler[type].compare (a, b);
+  else
+    {
+      fprintf (stderr, "unsupported value type: %d\n", type);
+      abort ();
+    }
+}
+
+void
+valprint (FILE *fp, mu_c_type_t type, union value *val)
+{
+  if ((size_t)type < sizeof (value_handler) / sizeof (value_handler[0])
+      && value_handler[type].format)
+    value_handler[type].format (val, fp);
+  else
+    {
+      fprintf (stderr, "unsupported value type: %d\n", type);
+      abort ();
+    }
+}
+
+struct testdata
+{
+  mu_c_type_t type;
+  char const *input;
+  int err;
+  union value val;
+};
+
+struct testdata tests[] = {
+  { mu_c_string, "now is the time", 0, { .v_string = "now is the time" } },
+  { mu_c_short,  "115",             0, { .v_short = 115 } },
+  { mu_c_short,  "-400",            0, { .v_short = -400 } },
+  { mu_c_short,  "1a",              EINVAL,  },
+
+  { mu_c_ushort, "110",             0, { .v_ushort = 110 } },
+  { mu_c_ushort, "-110",            ERANGE  },
+
+  { mu_c_int,    "10568",           0, { .v_int = 10568 } },
+  { mu_c_int,    "-10568",          0, { .v_int = -10568 } },
+
+  { mu_c_uint,   "10568",           0, { .v_uint = 10568 } },
+
+  { mu_c_long,   "10568",           0, { .v_long = 10568 } },
+  { mu_c_long,   "-10568",          0, { .v_long = -10568 } },
+
+  { mu_c_ulong,  "10568",           0, { .v_ulong = 10568 } },
+  
+  { mu_c_bool,   "true",            0, { .v_int = 1 } },
+  { mu_c_bool,   "false",           0, { .v_int = 0 } },
+
+  { mu_c_cidr,   "127.0.0.0/8",     0, { .v_cidr = {
+       .family = 2,
+       .len = 4,
+       .address = { 127, 0, 0, 0 },
+       .netmask = { 255 } } } },
+  { mu_c_cidr,   "fe80::4a5b:39ff:fe09:97f0/64", 0,  { .v_cidr = {
+       .family = 10,
+       .len = 16,
+       .address = { 0xfe, 0x80, 0x0,  0x0,  0x0,  0x0, 0x0,  0x0,
+                    0x4a, 0x5b, 0x39, 0xff, 0xfe, 0x9, 0x97, 0xf0 },
+       .netmask = { 255, 255, 255, 255, 255, 255, 255, 255,
+                    0,   0,   0,   0,   0,   0,   0,   0 } } } },
+  
+  { mu_c_incr,   NULL,              0, { .v_int = 1 } },
+  { mu_c_void }
+};
+
+void
+print_test_id (int i, FILE *fp)
+{
+  fprintf (fp, "%d: %s:%s: ", i, mu_c_type_str[tests[i].type],
+          tests[i].input ? tests[i].input : "NULL");
+}         
+
+void
+usage (int code, FILE *fp, char const *argv0)
+{
+  fprintf (fp, "usage: %s [-v]", argv0);
+  exit (code);
+}
+
+int
+main (int argc, char **argv)
+{
+  union value val;
+  char *errmsg;
+  int i;
+  unsigned failures = 0;
+  int verbose = 0;
+
+  for (i = 1; i < argc; i++) {
+    if (strcmp (argv[i], "-v") == 0)
+      verbose = 1;
+    else if (strcmp (argv[i], "-h") == 0)
+      usage (0, stdout, argv[0]);
+    else
+      usage (1, stderr, argv[0]);
+  }
+
+  if (i != argc)
+    usage (1, stderr, argv[0]);
+  
+  for (i = 0; tests[i].type != mu_c_void; i++)
+    {
+      int rc;
+
+      memset (&val, 0, sizeof (val));
+      rc = mu_str_to_c (tests[i].input, tests[i].type, &val, &errmsg);
+      if (rc)
+       {
+         if (tests[i].err == rc)
+           {
+             if (verbose)
+               {
+                 print_test_id (i, stdout);
+                 fprintf (stdout, "XFAIL\n");
+               }
+           }
+         else
+           {
+             print_test_id (i, stderr);
+             fprintf (stderr, "FAIL: error %s", mu_strerror (rc));
+             if (errmsg)
+               fprintf (stderr, ": %s", errmsg);
+             fputc ('\n', stderr);
+             free (errmsg);
+             ++failures;
+           }
+       }
+      else if (valcmp (tests[i].type, &tests[i].val, &val))
+       {
+         fprintf (stderr, "%d: FAIL: %s value differ: ",
+                  i, mu_c_type_str[tests[i].type]);
+         fprintf (stderr, "expected: ");
+         valprint (stderr, tests[i].type, &tests[i].val);
+         fprintf (stderr, ", but got: ");
+         valprint (stderr, tests[i].type, &val);
+         fputc ('\n', stderr);
+         ++failures;
+       }
+      else if (verbose)
+       {
+         print_test_id (i, stdout);
+         fprintf (stdout, "OK\n");
+       }
+    }
+  exit (!!failures);
+}
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index aa97088..be39fca 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -53,6 +53,34 @@ AT_CLEANUP
 
 AT_INIT
 
+AT_BANNER([Conversions])
+m4_include([strtoc.at])
+
+AT_BANNER([Command line parser])
+m4_include([parseopt00.at])
+m4_include([parseopt01.at])
+m4_include([parseopt02.at])
+m4_include([parseopt03.at])
+m4_include([parseopt04.at])
+m4_include([parseopt05.at])
+m4_include([parseopt06.at])
+m4_include([parseopt07.at])
+m4_include([parseopt08.at])
+m4_include([parseopt09.at])
+m4_include([parseopt10.at])
+m4_include([parseopt11.at])
+m4_include([parseopt12.at])
+m4_include([parseopt13.at])
+m4_include([parseopt14.at])
+m4_include([parseopt15.at])
+m4_include([parseopt16.at])
+m4_include([parseopt17.at])
+m4_include([parseopt18.at])
+m4_include([parseopt19.at])
+m4_include([parseopt20.at])
+m4_include([parseopt21.at])
+m4_include([parseopt22.at])
+
 AT_BANNER([Standard streams])
 m4_include([strin.at])
 m4_include([strout.at])
diff --git a/libmu_argp/muinit.c b/libmu_argp/muinit.c
index eb75fe3..50a4a9b 100644
--- a/libmu_argp/muinit.c
+++ b/libmu_argp/muinit.c
@@ -138,7 +138,7 @@ mu_app_init (struct argp *myargp, const char **capa,
       mu_stream_t stream;
       struct mu_cfg_cont *cont;
       static struct mu_cfg_param dummy_include_param[] = {
-       { "include", mu_cfg_string, NULL, 0, NULL,
+       { "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 "
diff --git a/libmu_cfg/common.c b/libmu_cfg/common.c
index 6028c6e..1684b7f 100644
--- a/libmu_cfg/common.c
+++ b/libmu_cfg/common.c
@@ -49,14 +49,14 @@ _cb_folder (void *data, mu_config_value_t *val)
 }
 
 static struct mu_cfg_param mu_mailbox_param[] = {
-  { "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool, 0, NULL,
+  { "mail-spool", mu_c_string, &mailbox_settings.mail_spool, 0, NULL,
     N_("Use specified URL as a mailspool directory."),
     N_("url") },
-  { "mailbox-pattern", mu_cfg_string, &mailbox_settings.mailbox_pattern,
+  { "mailbox-pattern", mu_c_string, &mailbox_settings.mailbox_pattern,
     0, NULL,
     N_("Create mailbox URL using <pattern>."),
     N_("pattern") },
-  { "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type, 0, NULL,
+  { "mailbox-type", mu_c_string, &mailbox_settings.mailbox_type, 0, NULL,
     N_("Default mailbox type."), N_("protocol") },
   { "folder", mu_cfg_callback, NULL, 0, _cb_folder,
     N_("Default user mail folder"),
@@ -73,17 +73,17 @@ DCL_CFG_CAPA (mailbox);
 
 static struct mu_cfg_param mu_locking_param[] = {
   /* FIXME: Flags are superfluous. */
-  { "flags", mu_cfg_string, &locking_settings.lock_flags, 0, NULL,
+  { "flags", mu_c_string, &locking_settings.lock_flags, 0, NULL,
     N_("Default locker flags (E=external, R=retry, T=time, P=pid).") },
-  { "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout,
+  { "retry-timeout", mu_c_ulong, &locking_settings.lock_retry_timeout,
     0, NULL,
     N_("Set timeout for acquiring the lock.") },
-  { "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count, 0, NULL,
+  { "retry-count", mu_c_ulong, &locking_settings.lock_retry_count, 0, NULL,
     N_("Set the maximum number of times to retry acquiring the lock.") },
-  { "expire-timeout", mu_cfg_ulong, &locking_settings.lock_expire_timeout,
+  { "expire-timeout", mu_c_ulong, &locking_settings.lock_expire_timeout,
     0, NULL,
     N_("Expire locks older than this amount of time.") },
-  { "external-locker", mu_cfg_string, &locking_settings.external_locker, 
+  { "external-locker", mu_c_string, &locking_settings.external_locker, 
     0, NULL,
     N_("Use external locker program."),
     N_("prog") },
@@ -98,11 +98,11 @@ DCL_CFG_CAPA (locking);
 /* ************************************************************************* */
      
 static struct mu_cfg_param mu_address_param[] = {
-  { "email-addr", mu_cfg_string, &address_settings.address, 0, NULL,
+  { "email-addr", mu_c_string, &address_settings.address, 0, NULL,
     N_("Set the current user email address (default is "
        "address@hidden)."),
     N_("email") },
-  { "email-domain", mu_cfg_string, &address_settings.domain, 0, NULL,
+  { "email-domain", mu_c_string, &address_settings.domain, 0, NULL,
     N_("Set e-mail domain for unqualified user names (default is this host)"),
     N_("domain") },
   { NULL }
@@ -116,7 +116,7 @@ DCL_CFG_CAPA (address);
 /* ************************************************************************* */
      
 static struct mu_cfg_param mu_mailer_param[] = {
-  { "url", mu_cfg_string, &mailer_settings.mailer, 0, NULL,
+  { "url", mu_c_string, &mailer_settings.mailer, 0, NULL,
     N_("Use this URL as the default mailer"),
     N_("url") },
   { NULL }
@@ -160,9 +160,9 @@ cb_severity (void *data, mu_config_value_t *val)
 }      
 
 static struct mu_cfg_param mu_logging_param[] = {
-  { "syslog", mu_cfg_bool, &mu_log_syslog, 0, NULL,
+  { "syslog", mu_c_bool, &mu_log_syslog, 0, NULL,
     N_("Send diagnostics to syslog.") },
-  { "print-severity", mu_cfg_bool, &mu_log_print_severity, 0, NULL,
+  { "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 "
@@ -171,9 +171,9 @@ static struct mu_cfg_param mu_logging_param[] = {
     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.") },
-  { "session-id", mu_cfg_bool, &mu_log_session_id, 0, NULL,
+  { "session-id", mu_c_bool, &mu_log_session_id, 0, NULL,
     N_("Log session ID") },
-  { "tag", mu_cfg_string, &mu_log_tag, 0, NULL,
+  { "tag", mu_c_string, &mu_log_tag, 0, NULL,
     N_("Tag syslog messages with this string.") },
   { NULL }
 };
@@ -204,7 +204,7 @@ static struct mu_cfg_param mu_debug_param[] = {
     N_("Set Mailutils debugging level.  Argument is a colon-separated list "
        "of debugging specifications in the form:\n"
        "   <object: string>[[:]=<level: number>].") },
-  { "line-info", mu_cfg_bool, &debug_settings.line_info, 0, NULL,
+  { "line-info", mu_c_bool, &debug_settings.line_info, 0, NULL,
     N_("Prefix debug messages with Mailutils source locations.") },
   { NULL }
 };
diff --git a/libmu_cfg/gsasl.c b/libmu_cfg/gsasl.c
index f4d3fbb..539f8b9 100644
--- a/libmu_cfg/gsasl.c
+++ b/libmu_cfg/gsasl.c
@@ -26,21 +26,21 @@
 static struct mu_gsasl_module_data gsasl_settings;
 
 static struct mu_cfg_param mu_gsasl_param[] = {
-  { "enable", mu_cfg_bool, &gsasl_settings.enable, 0, NULL,
+  { "enable", mu_c_bool, &gsasl_settings.enable, 0, NULL,
     N_("Enable GSASL (default)") },
-  { "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd, 0, NULL,
+  { "cram-passwd", mu_c_string, &gsasl_settings.cram_md5_pwd, 0, NULL,
     N_("Name of GSASL password file."),
     N_("file") },
-  { "service", mu_cfg_string, &gsasl_settings.service, 0, NULL,
+  { "service", mu_c_string, &gsasl_settings.service, 0, NULL,
     N_("SASL service name."),
     N_("name") },
-  { "realm", mu_cfg_string, &gsasl_settings.realm, 0, NULL,
+  { "realm", mu_c_string, &gsasl_settings.realm, 0, NULL,
     N_("SASL realm name."),
     N_("name") },
-  { "hostname", mu_cfg_string, &gsasl_settings.hostname, 0, NULL,
+  { "hostname", mu_c_string, &gsasl_settings.hostname, 0, NULL,
     N_("SASL host name."),
     N_("name") },
-  { "anonymous-user", mu_cfg_string, &gsasl_settings.anon_user, 0, NULL,
+  { "anonymous-user", mu_c_string, &gsasl_settings.anon_user, 0, NULL,
     N_("Anonymous user name."),
     N_("name") },
 
diff --git a/libmu_cfg/ldap.c b/libmu_cfg/ldap.c
index 1da6734..ec47165 100644
--- a/libmu_cfg/ldap.c
+++ b/libmu_cfg/ldap.c
@@ -43,22 +43,22 @@ cb_field_map (void *data, mu_config_value_t *val)
 }
 
 static struct mu_cfg_param mu_ldap_param[] = {
-  { "enable", mu_cfg_bool, &ldap_settings.enable, 0, NULL,
+  { "enable", mu_c_bool, &ldap_settings.enable, 0, NULL,
     N_("Enable LDAP lookups.") },
-  { "url", mu_cfg_string, &ldap_settings.url, 0, NULL,
+  { "url", mu_c_string, &ldap_settings.url, 0, NULL,
     N_("Set URL of the LDAP server."),
     N_("url") },
-  { "base", mu_cfg_string, &ldap_settings.base, 0, NULL,
+  { "base", mu_c_string, &ldap_settings.base, 0, NULL,
     N_("Base DN for LDAP lookups."),
     N_("dn") },
-  { "binddn", mu_cfg_string, &ldap_settings.binddn, 0, NULL,
+  { "binddn", mu_c_string, &ldap_settings.binddn, 0, NULL,
     N_("DN for accessing LDAP database."),
     N_("dn") },
-  { "passwd", mu_cfg_string, &ldap_settings.passwd, 0, NULL,
+  { "passwd", mu_c_string, &ldap_settings.passwd, 0, NULL,
     N_("Password for use with binddn.") },
-  { "tls", mu_cfg_bool, &ldap_settings.tls, 0, NULL,
+  { "tls", mu_c_bool, &ldap_settings.tls, 0, NULL,
     N_("Use TLS encryption.") },
-  { "debug", mu_cfg_int, &ldap_settings.debug, 0, NULL,
+  { "debug", mu_c_int, &ldap_settings.debug, 0, NULL,
     N_("Set LDAP debugging level.") },
   { "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
     N_("Set a field-map for parsing LDAP replies.  The map is a "
@@ -69,10 +69,10 @@ static struct mu_cfg_param mu_ldap_param[] = {
        "gecos, dir, shell, mailbox, quota, and <attr> is the name of "
        "the corresponding LDAP attribute."),
     N_("map") },
-  { "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter, 0, NULL,
+  { "getpwnam", mu_c_string, &ldap_settings.getpwnam_filter, 0, NULL,
     N_("LDAP filter to use for getpwnam requests."),
     N_("filter") },
-  { "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter, 0, NULL,
+  { "getpwuid", mu_c_string, &ldap_settings.getpwuid_filter, 0, NULL,
     N_("LDAP filter to use for getpwuid requests."),
     N_("filter") },
   { NULL }
diff --git a/libmu_cfg/pam.c b/libmu_cfg/pam.c
index 33d50ab..ec8c9cc 100644
--- a/libmu_cfg/pam.c
+++ b/libmu_cfg/pam.c
@@ -25,7 +25,7 @@
 static char *pam_settings;
 
 static struct mu_cfg_param mu_pam_param[] = {
-  { "service", mu_cfg_string, &pam_settings, 0, NULL,
+  { "service", mu_c_string, &pam_settings, 0, NULL,
     N_("Set PAM service name."),
     N_("name") },
   { NULL }
diff --git a/libmu_cfg/radius.c b/libmu_cfg/radius.c
index cee0713..fb874a6 100644
--- a/libmu_cfg/radius.c
+++ b/libmu_cfg/radius.c
@@ -26,16 +26,16 @@
 static struct mu_radius_module_data radius_settings;
 
 static struct mu_cfg_param mu_radius_param[] = {
-  { "auth", mu_cfg_string, &radius_settings.auth_request, 0, NULL,
+  { "auth", mu_c_string, &radius_settings.auth_request, 0, NULL,
     N_("Radius request for authorization."),
     N_("request") },
-  { "getpwnam", mu_cfg_string, &radius_settings.getpwnam_request, 0, NULL,
+  { "getpwnam", mu_c_string, &radius_settings.getpwnam_request, 0, NULL,
     N_("Radius request for getpwnam."),
     N_("request") },
-  { "getpwuid", mu_cfg_string, &radius_settings.getpwuid_request, 0, NULL,
+  { "getpwuid", mu_c_string, &radius_settings.getpwuid_request, 0, NULL,
     N_("Radius request for getpwuid."),
     N_("request") },
-  { "directory", mu_cfg_string, &radius_settings.config_dir, 0, NULL,
+  { "directory", mu_c_string, &radius_settings.config_dir, 0, NULL,
     N_("Set radius configuration directory.") },
   { NULL }
 };
diff --git a/libmu_cfg/sieve.c b/libmu_cfg/sieve.c
index bd38f5d..fb4f106 100644
--- a/libmu_cfg/sieve.c
+++ b/libmu_cfg/sieve.c
@@ -32,7 +32,7 @@ cb_clear_library_path (void *data, mu_config_value_t *val)
 
   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
     return 1;
-  if (mu_cfg_parse_boolean (val->v.string, &flag))
+  if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL))
     {
       mu_error (_("not a boolean"));
       return 1;
@@ -49,7 +49,7 @@ cb_clear_include_path (void *data, mu_config_value_t *val)
   
   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
     return 1;
-  if (mu_cfg_parse_boolean (val->v.string, &flag))
+  if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL))
     {
       mu_error (_("not a boolean"));
       return 1;
diff --git a/libmu_cfg/sql.c b/libmu_cfg/sql.c
index fbacff0..af60300 100644
--- a/libmu_cfg/sql.c
+++ b/libmu_cfg/sql.c
@@ -57,31 +57,31 @@ cb_field_map (void *data, mu_config_value_t *val)
 }
 
 static struct mu_cfg_param mu_sql_param[] = {
-  { "interface", mu_cfg_string, &sql_settings.interface, 0, NULL,
+  { "interface", mu_c_string, &sql_settings.interface, 0, NULL,
     N_("Set SQL interface to use (one of: mysql, odbc, or postgres).") },
-  { "getpwnam", mu_cfg_string, &sql_settings.getpwnam_query, 0, NULL,
+  { "getpwnam", mu_c_string, &sql_settings.getpwnam_query, 0, NULL,
     N_("SQL query to use for getpwnam requests."),
     N_("query") },
-  { "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query, 0, NULL,
+  { "getpwuid", mu_c_string, &sql_settings.getpwuid_query, 0, NULL,
     N_("SQL query to use for getpwuid requests."),
     N_("query") },
-  { "getpass", mu_cfg_string, &sql_settings.getpass_query, 0, NULL,
+  { "getpass", mu_c_string, &sql_settings.getpass_query, 0, NULL,
     N_("SQL query returning the user's password."),
     N_("query") },
-  { "host", mu_cfg_string, &sql_settings.host, 0, NULL,
+  { "host", mu_c_string, &sql_settings.host, 0, NULL,
     N_("SQL server host name.") },
-  { "user", mu_cfg_string, &sql_settings.user, 0, NULL,
+  { "user", mu_c_string, &sql_settings.user, 0, NULL,
     N_("SQL user name.") },
-  { "passwd", mu_cfg_string, &sql_settings.passwd, 0, NULL,
+  { "passwd", mu_c_string, &sql_settings.passwd, 0, NULL,
     N_("Password for the SQL user.") },
-  { "port", mu_cfg_int, &sql_settings.port, 0, NULL,
+  { "port", mu_c_int, &sql_settings.port, 0, NULL,
     N_("SQL server port.") },
-  { "db", mu_cfg_string, &sql_settings.db, 0, NULL,
+  { "db", mu_c_string, &sql_settings.db, 0, NULL,
     N_("Database name.") },
   { "password-type", mu_cfg_callback, NULL, 0, cb_password_type,
     N_("Type of password returned by getpass query (one of: plain, hash, "
        "scrambled).") },
-  { "positional", mu_cfg_bool, &sql_settings.positional, 0, NULL,
+  { "positional", mu_c_bool, &sql_settings.positional, 0, NULL,
     N_("Use positional (v1.0 compatible) field interface.") },
   { "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
     N_("Set a field-map for parsing SQL replies.  The map is a "
diff --git a/libmu_cfg/tls.c b/libmu_cfg/tls.c
index 2004cbe..3d568ef 100644
--- a/libmu_cfg/tls.c
+++ b/libmu_cfg/tls.c
@@ -77,18 +77,18 @@ cb_safety_checks (void *data, mu_config_value_t *arg)
 }
 
 static struct mu_cfg_param mu_tls_param[] = {
-  { "enable", mu_cfg_bool, &tls_settings.enable, 0, NULL,
+  { "enable", mu_c_bool, &tls_settings.enable, 0, NULL,
     N_("Enable TLS encryption.") },
-  { "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert, 0, NULL,
+  { "ssl-cert", mu_c_string, &tls_settings.ssl_cert, 0, NULL,
     N_("Specify SSL certificate file."),
     N_("file") },
-  { "ssl-key", mu_cfg_string, &tls_settings.ssl_key, 0, NULL,
+  { "ssl-key", mu_c_string, &tls_settings.ssl_key, 0, NULL,
     N_("Specify SSL certificate key file."),
     N_("file") },
-  { "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile, 0, NULL,
+  { "ssl-cafile", mu_c_string, &tls_settings.ssl_cafile, 0, NULL,
     N_("Specify trusted CAs file."),
     N_("file") },
-  { "ssl-priorities", mu_cfg_string, &tls_settings.priorities, 0, NULL,
+  { "ssl-priorities", mu_c_string, &tls_settings.priorities, 0, NULL,
     N_("Set the priorities to use on the ciphers, key exchange methods, "
        "macs and compression methods."),
     NULL },
diff --git a/libmu_cfg/virtdomain.c b/libmu_cfg/virtdomain.c
index c2dc2cc..d4e2d1e 100644
--- a/libmu_cfg/virtdomain.c
+++ b/libmu_cfg/virtdomain.c
@@ -25,7 +25,7 @@
 static struct mu_gocs_virtual virtdomain_settings;
 
 static struct mu_cfg_param mu_virtdomain_param[] = {
-  { "passwd-dir", mu_cfg_string, &virtdomain_settings, 0, NULL,
+  { "passwd-dir", mu_c_string, &virtdomain_settings, 0, NULL,
     N_("Name of the directory where virtual domain password files are "
        "located."),
     N_("dir") },
diff --git a/maidag/maidag.c b/maidag/maidag.c
index 0eac0c4..85d757b 100644
--- a/maidag/maidag.c
+++ b/maidag/maidag.c
@@ -284,7 +284,7 @@ cb_stderr (void *data, mu_config_value_t *val)
   
   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
     return 1;
-  if (mu_cfg_parse_boolean (val->v.string, &res))
+  if (mu_str_to_c (val->v.string, mu_c_bool, &res, NULL))
     mu_error (_("not a boolean"));
   else
     mu_log_syslog = !res;
@@ -415,24 +415,24 @@ struct mu_cfg_param maidag_cfg_param[] = {
   { "delivery-mode", mu_cfg_callback, NULL, 0, cb_delivery_mode,
     N_("Set delivery mode"),
     N_("mode: {mda | url | lmtp}") },
-  { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL,
+  { "exit-multiple-delivery-success", mu_c_bool, &multiple_delivery, 0, NULL,
     N_("In case of multiple delivery, exit with code 0 if at least one "
        "delivery succeeded.") },
-  { "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
+  { "exit-quota-tempfail", mu_c_bool, &ex_quota_tempfail, 0, NULL,
     N_("Indicate temporary failure if the recipient is over his mail quota.")
   },
 #ifdef ENABLE_DBM
-  { "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
+  { "quota-db", mu_c_string, &quotadbname, 0, NULL,
     N_("Name of DBM quota database file."),
     N_("file") },
 #endif
 #ifdef USE_SQL
-  { "quota-query", mu_cfg_string, &quota_query, 0, NULL,
+  { "quota-query", mu_c_string, &quota_query, 0, NULL,
     N_("SQL query to retrieve mailbox quota.  This is deprecated, use "
        "sql { ... } instead."),
     N_("query") },
 #endif
-  { "message-id-header", mu_cfg_string, &message_id_header, 0, NULL,
+  { "message-id-header", mu_c_string, &message_id_header, 0, NULL,
     N_("When logging Sieve actions, identify messages by the value of "
        "this header."),
     N_("name") },
@@ -445,12 +445,12 @@ struct mu_cfg_param maidag_cfg_param[] = {
        "  l - sieve action logs\n") },
   { "stderr", mu_cfg_callback, NULL, 0, cb_stderr,
     N_("Log to stderr instead of syslog.") },
-  { "forward-file", mu_cfg_string, &forward_file, 0, NULL,
+  { "forward-file", mu_c_string, &forward_file, 0, NULL,
     N_("Process forward file.") },
   { "forward-file-checks", mu_cfg_callback, NULL, 0, cb_forward_file_checks,
     N_("Configure safety checks for the forward file."),
     N_("arg: list") },
-  { "domain", mu_cfg_string, &default_domain, 0, NULL,
+  { "domain", mu_c_string, &default_domain, 0, NULL,
     N_("Default email domain") },
 /* LMTP support */
   { "group", mu_cfg_callback, &lmtp_groups, 0, cb_group,
@@ -463,7 +463,7 @@ struct mu_cfg_param maidag_cfg_param[] = {
        "   file://<socket-file-name>\n"
        "or socket://<socket-file-name>"),
     N_("url") },
-  { "reuse-address", mu_cfg_bool, &reuse_lmtp_address, 0, NULL,
+  { "reuse-address", mu_c_bool, &reuse_lmtp_address, 0, NULL,
     N_("Reuse existing address (LMTP mode).  Default is \"yes\".") },
   { "filter", mu_cfg_section, NULL, 0, NULL,
     N_("Add a message filter") },
diff --git a/mail/unset.c b/mail/unset.c
index d829ef9..45526b1 100644
--- a/mail/unset.c
+++ b/mail/unset.c
@@ -26,7 +26,7 @@ mail_unset (int argc, char **argv)
 {
   if (argc < 2)
     {
-      mailvar_print (0);
+      mailvar_print (1);
       return 0;
     }
   else
diff --git a/mh/rmf.c b/mh/rmf.c
index 9cf652f..2e8c47f 100644
--- a/mh/rmf.c
+++ b/mh/rmf.c
@@ -92,7 +92,7 @@ opt_handler (int key, char *arg, struct argp_state *state)
 }
 
 static char *
-current_folder_path ()
+current_folder_path (void)
 {
   mu_mailbox_t mbox = mh_open_folder (mh_current_folder (), MU_STREAM_RDWR);
   mu_url_t url;
@@ -197,7 +197,7 @@ main (int argc, char **argv)
       name = cur_folder_path;
     }
   else
-    name = mh_expand_name (NULL, folder_name, NAME_ANY);
+    name = mh_expand_name (NULL, folder_name, NAME_FOLDER);
   if (recursive)
     status = recrmf (name);
   else
diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c
index 0bc7bf6..4a7810c 100644
--- a/mimeview/mimeview.c
+++ b/mimeview/mimeview.c
@@ -164,10 +164,10 @@ struct mu_cfg_param mimeview_cfg_param[] = {
   { "debug", mu_cfg_callback, NULL, 0, cb_debug,
     N_("Set debug verbosity level."),
     N_("flags") },
-  { "mimetypes", mu_cfg_string, &mimetypes_config, 0, NULL,
+  { "mimetypes", mu_c_string, &mimetypes_config, 0, NULL,
     N_("Use this mime.types file."),
     N_("file") },
-  { "metamail", mu_cfg_string, &metamail, 0, NULL,
+  { "metamail", mu_c_string, &metamail, 0, NULL,
     N_("Use this program to display files."),
     N_("prog") },
   { NULL }
diff --git a/movemail/movemail.c b/movemail/movemail.c
index 888a015..67b721f 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -371,17 +371,17 @@ cb_onerror (void *data, mu_config_value_t *val)
 }
   
 struct mu_cfg_param movemail_cfg_param[] = {
-  { "preserve", mu_cfg_bool, &preserve_mail, 0, NULL,
+  { "preserve", mu_c_bool, &preserve_mail, 0, NULL,
     N_("Do not remove messages from the source mailbox.") },
-  { "reverse",  mu_cfg_bool, &reverse_order, 0, NULL,
+  { "reverse",  mu_c_bool, &reverse_order, 0, NULL,
     N_("Reverse message sorting order.") },
-  { "emacs", mu_cfg_bool, &emacs_mode, 0, NULL,
+  { "emacs", mu_c_bool, &emacs_mode, 0, NULL,
     N_("Output information used by Emacs rmail interface.") },
-  { "uidl", mu_cfg_bool, &uidl_option, 0, NULL,
+  { "uidl", mu_c_bool, &uidl_option, 0, NULL,
     N_("Use UIDLs to avoid downloading the same message twice.") },
-  { "verbose", mu_cfg_int, &verbose_option, 0, NULL,
+  { "verbose", mu_c_int, &verbose_option, 0, NULL,
     N_("Set verbosity level.") },
-  { "program-id", mu_cfg_string, &program_id_option, 0, NULL,
+  { "program-id", mu_c_string, &program_id_option, 0, NULL,
     N_("Set program identifier string (default: program name)") },
   { "mailbox-ownership", mu_cfg_callback, NULL, 0,
     cb_mailbox_ownership,
@@ -392,10 +392,10 @@ struct mu_cfg_param movemail_cfg_param[] = {
        " set-id=UID[:GID] set supplied UID and GID\n"
        " set-name=USER    make destination mailbox owned by USER"),
     N_("methods: list") },
-  { "max-messages", mu_cfg_size, &max_messages_option, 0, NULL,
+  { "max-messages", mu_c_size, &max_messages_option, 0, NULL,
     N_("Copy at most <count> messages."),
     N_("count") },
-  { "ignore-errors", mu_cfg_bool, &ignore_errors, 0, NULL,
+  { "ignore-errors", mu_c_bool, &ignore_errors, 0, NULL,
     N_("Continue after an error.") },
   { "onerror", mu_cfg_callback, NULL, 0, cb_onerror,
     N_("What to do after an error. Argument is a comma-separated list of:\n"
diff --git a/pop3d/pop3d.c b/pop3d/pop3d.c
index 90f04f9..ca1a1af 100644
--- a/pop3d/pop3d.c
+++ b/pop3d/pop3d.c
@@ -182,7 +182,7 @@ cb_tls_required (void *data, mu_config_value_t *val)
   
   if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
     return 1;
-  if (mu_cfg_parse_boolean (val->v.string, &bv))
+  if (mu_str_to_c (val->v.string, mu_c_bool, &bv, NULL))
     mu_error (_("Not a boolean value"));
   else if (bv)
     {
@@ -210,16 +210,16 @@ static struct mu_cfg_param pop3d_srv_param[] = {
 };
     
 static struct mu_cfg_param pop3d_cfg_param[] = {
-  { "undelete", mu_cfg_bool, &undelete_on_startup, 0, NULL,
+  { "undelete", mu_c_bool, &undelete_on_startup, 0, NULL,
     N_("On startup, clear deletion marks from all the messages.") },
-  { "expire", mu_cfg_uint, &expire, 0, NULL,
+  { "expire", mu_c_uint, &expire, 0, NULL,
     N_("Automatically expire read messages after the given number of days."),
     N_("days") },
-  { "delete-expired", mu_cfg_bool, &expire_on_exit, 0, NULL,
+  { "delete-expired", mu_c_bool, &expire_on_exit, 0, NULL,
     N_("Delete expired messages upon closing the mailbox.") },
-  { "scan-lines", mu_cfg_bool, &pop3d_xlines, 0, NULL,
+  { "scan-lines", mu_c_bool, &pop3d_xlines, 0, NULL,
     N_("Output the number of lines in the message in its scan listing.") },
-  { "apop-database-file", mu_cfg_string, &apop_database_name, 0, NULL,
+  { "apop-database-file", mu_c_string, &apop_database_name, 0, NULL,
     N_("set APOP database file name or URL") },
   { "apop-database-owner", mu_cfg_callback, NULL, 0, cb_apop_database_owner,
     N_("Name or UID of the APOP database owner") },
@@ -247,9 +247,9 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
        "Deprecated, use \"tls required\" instead.") },
 #endif
 #ifdef ENABLE_LOGIN_DELAY
-  { "login-delay", mu_cfg_time, &login_delay, 0, NULL,
+  { "login-delay", mu_c_time, &login_delay, 0, NULL,
     N_("Set the minimal allowed delay between two successive logins.") },
-  { "stat-file", mu_cfg_string, &login_stat_file, 0, NULL,
+  { "stat-file", mu_c_string, &login_stat_file, 0, NULL,
     N_("Set the name of login statistics file (for login-delay).") },
 #endif
   { "bulletin-source", mu_cfg_callback, NULL, 0, cb_bulletin_source,
@@ -260,12 +260,12 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
     N_("Set the bulletin database file name."),
     N_("file") },
 #endif
-  { "output-buffer-size", mu_cfg_size, &pop3d_output_bufsize, 0, NULL,
+  { "output-buffer-size", mu_c_size, &pop3d_output_bufsize, 0, NULL,
     N_("Size of the output buffer.") },
   { "mandatory-locking", mu_cfg_section },
   { ".server", mu_cfg_section, NULL, 0, NULL,
     N_("Server configuration.") },
-  { "transcript", mu_cfg_bool, &pop3d_transcript, 0, NULL,
+  { "transcript", mu_c_bool, &pop3d_transcript, 0, NULL,
     N_("Set global transcript mode.") },
   TCP_WRAPPERS_CONFIG
   { NULL }
diff --git a/readmsg/readmsg.c b/readmsg/readmsg.c
index 485f925..794c0f1 100644
--- a/readmsg/readmsg.c
+++ b/readmsg/readmsg.c
@@ -126,21 +126,21 @@ readmsg_parse_opt (int key, char *arg, struct argp_state 
*astate)
 
 
 struct mu_cfg_param readmsg_cfg_param[] = {
-  { "debug", mu_cfg_int, &dbug, 0, NULL,
+  { "debug", mu_c_int, &dbug, 0, NULL,
     N_("Set debug verbosity level.") },
-  { "header", mu_cfg_bool, &all_header, 0, NULL,
+  { "header", mu_c_bool, &all_header, 0, NULL,
     N_("Display entire headers.") },
-  { "weedlist", mu_cfg_string, &weedlist, 0, NULL,
+  { "weedlist", mu_c_string, &weedlist, 0, NULL,
     N_("Display only headers from this list.  Argument is a list of header "
        "names separated by whitespace or commas."),
     N_("list") },
-  { "folder", mu_cfg_string, &mailbox_name, 0, NULL,
+  { "folder", mu_c_string, &mailbox_name, 0, NULL,
     N_("Read messages from this folder.") },
-  { "no-header", mu_cfg_bool, &no_header, 0, NULL,
+  { "no-header", mu_c_bool, &no_header, 0, NULL,
     N_("Exclude all headers.") }, 
-  { "form-feeds", mu_cfg_bool, &form_feed, 0, NULL,
+  { "form-feeds", mu_c_bool, &form_feed, 0, NULL,
     N_("Output formfeed character between messages.") },
-  { "show-all-match", mu_cfg_bool, &show_all, 0, NULL,
+  { "show-all-match", mu_c_bool, &show_all, 0, NULL,
     N_("Print all messages matching pattern, not only the first.") },
   { NULL }
 };
diff --git a/sieve/sieve.c b/sieve/sieve.c
index 182b291..32a8a0b 100644
--- a/sieve/sieve.c
+++ b/sieve/sieve.c
@@ -281,12 +281,12 @@ cb_email (void *data, mu_config_value_t *val)
 }
 
 static struct mu_cfg_param sieve_cfg_param[] = {
-  { "keep-going", mu_cfg_bool, &keep_going, 0, NULL,
+  { "keep-going", mu_c_bool, &keep_going, 0, NULL,
     N_("Do not abort if execution fails on a message.") },
-  { "mbox-url", mu_cfg_string, &mbox_url, 0, NULL,
+  { "mbox-url", mu_c_string, &mbox_url, 0, NULL,
     N_("Mailbox to sieve (defaults to user's mail spool)."),
     N_("url") },
-  { "ticket", mu_cfg_string, &mu_ticket_file, 0, NULL,
+  { "ticket", mu_c_string, &mu_ticket_file, 0, NULL,
     N_("Ticket file for user authentication."),
     N_("ticket") },
   { "debug", mu_cfg_callback, NULL, 0, cb_debug,
@@ -297,9 +297,9 @@ static struct mu_cfg_param sieve_cfg_param[] = {
        "   P - network protocols (sieve.prot)\n"
        "   t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
        "   i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR).") },
-  { "verbose", mu_cfg_bool, &verbose, 0, NULL,
+  { "verbose", mu_c_bool, &verbose, 0, NULL,
     N_("Log all executed actions.") },
-  { "line-info", mu_cfg_bool, &sieve_print_locus, 0, NULL,
+  { "line-info", mu_c_bool, &sieve_print_locus, 0, NULL,
     N_("Print source locations along with action logs (default).") },
   { "email", mu_cfg_callback, NULL, 0, cb_email,
     N_("Set user email address.") },


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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