summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-11-17 10:20:52 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-11-17 13:24:51 +0200
commit823e48a02f8952c0550bbec6bc2e3849c41cf011 (patch)
tree623ecb692a8415a5a4ebf260858a0716176ac261
parent6e0fb32ec8557a443e7ea110bc923dfd7b79ae03 (diff)
downloadmailutils-823e48a02f8952c0550bbec6bc2e3849c41cf011.tar.gz
mailutils-823e48a02f8952c0550bbec6bc2e3849c41cf011.tar.bz2
New mailutils subcommand: maildir_fixup
The subcommand converts names in maildirs created by earlier versions of mailutils to the new format. * NEWS: Update. * doc/texinfo/programs/mailutils.texi: Document maildir_fixup * mu/libexec/Makefile.am: Build maildir_fixup subcommand. * mu/libexec/maildir_fixup.c: New file. * mu/libexec/mu.h (common_options): New extern. * include/mailutils/cli.h (MU_CLI_OPTION_CONF_PROGNAME): New constant. * libmailutils/cli/simple.c (MU_CLI_OPTION_PROG_NAME) (MU_CLI_OPTION_PROG_NAME) (MU_CLI_OPTION_PROG_DOC) (MU_CLI_OPTION_BUG_ADDRESS) (MU_CLI_OPTION_PACKAGE_URL) (MU_CLI_OPTION_EXTRA_INFO) (MU_CLI_OPTION_HELP_HOOK) (MU_CLI_OPTION_VERSION_HOOK) (MU_CLI_OPTION_PROG_DOC_HOOK) (MU_CLI_OPTION_NEGATION) (MU_CLI_OPTION_SPECIAL_ARGS): Allow for NULL argument. (MU_CLI_OPTION_CONF_PROGNAME): New code
-rw-r--r--NEWS12
-rw-r--r--doc/texinfo/programs/mailutils.texi57
-rw-r--r--include/mailutils/cli.h27
-rw-r--r--lib/manlock.c4
-rw-r--r--libmailutils/cli/simple.c38
-rw-r--r--mu/libexec/Makefile.am10
-rw-r--r--mu/libexec/maildir_fixup.c202
-rw-r--r--mu/libexec/mu.h1
8 files changed, 333 insertions, 18 deletions
diff --git a/NEWS b/NEWS
index e5531a6ad..46360a722 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2020-11-10
+GNU mailutils NEWS -- history of user-visible changes. 2020-11-17
See the end of file for copying conditions.
Please send mailutils bug reports to <bug-mailutils@gnu.org>.
@@ -18,6 +18,16 @@ incorrect flag mapping and fixes it if so. If the mailbox is opened
in read-write mode, the changes are immediately propagated to the disk
storage.
+An auxiliary tool `maildir_fixup' is provided to fix up all maildirs
+in given folders recursively. The tool can be used if you operate a
+site with a large number of mailboxes in maildir format and wish to
+convert all of them at once. It is implemented as a subcommand of the
+`mailutils' utility. Example usage:
+
+ mailutils maildir_fixup /var/spool/maildirs
+
+* Fix persistency of UIDs for all mailbox formats
+
* Fix message ordering in maildir.
* Fix parsing of IMAP ranges
diff --git a/doc/texinfo/programs/mailutils.texi b/doc/texinfo/programs/mailutils.texi
index d4769b85e..176d897df 100644
--- a/doc/texinfo/programs/mailutils.texi
+++ b/doc/texinfo/programs/mailutils.texi
@@ -26,6 +26,7 @@ with Mailutils.
* mailutils imap:: IMAP4 client shell.
* mailutils send:: Send a message.
* mailutils smtp:: Run a SMTP session.
+* mailutils maildir_fixup:: Fix-up maildirs created by versions prior to 3.10.90
@end menu
@node mailutils invocation syntax
@@ -1450,3 +1451,59 @@ message: send, edit, or quit (discard) it.
Internal commands are the same as in @code{pop} shell: @xref{mailutils
pop, Internal commands}.
+@node mailutils maildir_fixup
+@subsection mailutils maildir_fixup
+
+This command fixes attributes and UID assignments in @samp{maildir}
+mailboxes created by mailutils versions prior to 3.10.90.
+
+Attribute flags used in @samp{maildir} mailboxes by these versions of
+mailutils were a bit different from those described in the original
+description of the @samp{maildir} format@footnote{@uref{http://cr.yp.to/proto/maildir.html}}
+and those used by another implementations. The discrepancy has been
+reported in the Mailutils bug tracker@footnote{@uref{http://savannah.gnu.org/bugs/?56428}}
+and was fixed in version 3.10.90. Along with this fix, measures has
+been taken to ensure persistence of UID assignments between different
+sessions. Starting from version 3.10.90, whenever @command{mailutils}
+library opens a maildir mailbox, it determines the version that
+created it. If the mailbox is writable and the library determines
+that the mailbox is affected by the two problems described above, it
+fixes the mailbox on the fly. This process is completely transparent
+to the user.
+
+If you operate a site with a large number of mailboxes in
+@samp{maildir} formats, you may choose to fix up all of them at once.
+That's what the @command{maildir_fixup} command is for. It takes one
+or more directory names as its arguments and recursively scans these
+directories in search for @samp{maildir} mailboxes. Each mailbox
+found is analyzed and a fix-up is performed, if necessary. If a
+mailbox is already in the new format, it remains untouched.
+
+The following options modify the program's behavior:
+
+@table @option
+@item -v
+@itemx --verbose
+List each maildir name before processing it.
+
+@item -n
+@itemx --dry-run
+Don't touch maildirs, just print their names,
+@end table
+
+The @command{maildir_fixup} tool reads main mailutils configuration
+file by default. It looks for program-specific settings in the
+section @samp{program maildir_fixup}. If the @code{include} statement
+is present that has a directory name as its argument, the file
+@file{maildir_fixup} is looked up in that directory and parsed, if
+present.
+
+The program uses the following configuration statements:
+
+@multitable @columnfractions 0.3 0.6
+@headitem Statement @tab Reference
+@item debug @tab @xref{debug statement}.
+@item locking @tab @xref{locking statement}.
+@item mandatory-locking @tab @FIXME-xref{mandatory-locking statement}.
+@end multitable
+
diff --git a/include/mailutils/cli.h b/include/mailutils/cli.h
index 9d2afc806..18ce2c341 100644
--- a/include/mailutils/cli.h
+++ b/include/mailutils/cli.h
@@ -89,12 +89,14 @@ enum
/* Argument: struct mu_cfg_param *
* Description: Supplies configuration definitions.
+ * NULL argument is a no-op.
* Ref: cfg in struct mu_cli_setup
*/
MU_CLI_OPTION_CONFIG,
/* Argument: char **
* Description: NULL-terminated array of capability strings.
+ * NULL argument is a no-op.
* Ref: capa argument to mu_cli and mu_cli_ext.
*/
MU_CLI_OPTION_CAPABILITIES,
@@ -167,6 +169,7 @@ enum
/* Argument: char const *
* Description: Override the name of the program to use in error
* messages.
+ * NULL argument is a no-op.
* Ref: MU_PARSEOPT_PROG_NAME flag in opt.h
*/
MU_CLI_OPTION_PROG_NAME,
@@ -174,6 +177,7 @@ enum
/* Argument: char const *
* Description: Documentation string for the program. It will be
* displayed on the line following the usage summary.
+ * NULL argument is a no-op.
* Ref: MU_PARSEOPT_PROG_DOC
*/
MU_CLI_OPTION_PROG_DOC,
@@ -186,6 +190,7 @@ enum
* Usage: foo A B
*
* Multiple instances are allowed.
+ * NULL argument is a no-op.
* Ref: MU_PARSEOPT_PROG_ARGS flag in opt.h
*/
MU_CLI_OPTION_PROG_ARGS,
@@ -198,12 +203,14 @@ enum
/* Argument: char const *
* Description: Sets the PACKAGE_NAME.
+ * NULL argument is a no-op.
* Ref: MU_PARSEOPT_PACKAGE_NAME in opt.h
*/
MU_CLI_OPTION_PACKAGE_NAME,
/* Argument: char const *
* Description: URL of the package.
+ * NULL argument is a no-op.
* Ref: MU_PARSEOPT_PACKAGE_URL in opt.h
*/
MU_CLI_OPTION_PACKAGE_URL,
@@ -211,6 +218,7 @@ enum
/* Argument: char const *
* Description: Extra help information. This will be displayed after
* the option list.
+ * NULL argument is a no-op.
* Ref: MU_PARSEOPT_EXTRA_INFO in opt.h
*/
MU_CLI_OPTION_EXTRA_INFO,
@@ -218,6 +226,7 @@ enum
/* Argument: void (*) (struct mu_parseopt *, mu_stream_t)
* Description: Pointer to a function to be called as a part of the
* --help option handling, after outputting the option list.
+ * NULL argument is a no-op.
* Ref: po_help_hook member of struct mu_parseopt and the
* MU_PARSEOPT_HELP_HOOK flag in opt.h
*/
@@ -243,7 +252,9 @@ enum
* --help option handling. This function will be called after printing
* initial program description (see MU_CLI_OPTION_PROG_DOC) and before
* printing the option summary.
- * Ref:
+ * NULL argument is a no-op.
+ * Ref: po_prog_doc_hook member of struct mu_parseopt and the
+ * MU_PARSEOPT_PROG_DOC_HOOK in opt.h
*/
MU_CLI_OPTION_PROG_DOC_HOOK,
@@ -256,6 +267,7 @@ enum
/* Argument: char const *
* Description: Prefix that negates the value of a boolean option.
+ * NULL argument is a no-op.
* Ref: po_negation member of struct mu_parseopt and the
* MU_PARSEOPT_NEGATION flag in opt.h
*/
@@ -264,6 +276,7 @@ enum
/* Argument: char const *
* Description: Descriptive names of special arguments. If given, this
* will be printed in short usage summary after the regular options.
+ * NULL argument is a no-op.
* Ref: The po_special_args member of struct mu_parseopt and the
* MU_PARSEOPT_SPECIAL_ARGS flag in opt.h
*/
@@ -289,7 +302,17 @@ enum
* from the command line.
* Ref: MU_CFHINT_NO_CONFIG_OVERRIDE flag in cfg.h
*/
- MU_CLI_OPTION_CONF_NO_OVERRIDE
+ MU_CLI_OPTION_CONF_NO_OVERRIDE,
+
+ /* Argument: char const *
+ * Description: Identifier of the per-program section in the configuration
+ * file or name of the per-program configuration file (used when
+ * processing the "include" statement with a directory name as its
+ * argument). If NULL or not set, program name is used. See also
+ * MU_CLI_OPTION_PROG_NAME.
+ * Ref: MU_CFHINT_PROGRAM flag in cfg.h
+ */
+ MU_CLI_OPTION_CONF_PROGNAME,
};
void mu_cli_simple (int argc, char **argv, ...);
diff --git a/lib/manlock.c b/lib/manlock.c
index a093a1926..f50e16343 100644
--- a/lib/manlock.c
+++ b/lib/manlock.c
@@ -237,10 +237,6 @@ manlock_cfg_init ()
mu_create_canned_section ("mandatory-locking", &section);
mu_cfg_section_add_params (section, manlock_param);
}
-
-
-
-
int
manlock_lock (mu_mailbox_t mbox)
diff --git a/libmailutils/cli/simple.c b/libmailutils/cli/simple.c
index 0daef170d..20adcc11b 100644
--- a/libmailutils/cli/simple.c
+++ b/libmailutils/cli/simple.c
@@ -117,13 +117,15 @@ mu_cli_simple (int argc, char **argv, ...)
break;
case MU_CLI_OPTION_PROG_NAME:
- pohint.po_flags |= MU_PARSEOPT_PROG_NAME;
pohint.po_prog_name = va_arg (ap, char *);
+ if (pohint.po_prog_name)
+ pohint.po_flags |= MU_PARSEOPT_PROG_NAME;
break;
case MU_CLI_OPTION_PROG_DOC:
- pohint.po_flags |= MU_PARSEOPT_PROG_DOC;
pohint.po_prog_doc = va_arg (ap, char *);
+ if (pohint.po_prog_doc)
+ pohint.po_flags |= MU_PARSEOPT_PROG_DOC;
break;
case MU_CLI_OPTION_PROG_ARGS:
@@ -137,51 +139,60 @@ mu_cli_simple (int argc, char **argv, ...)
break;
case MU_CLI_OPTION_BUG_ADDRESS:
- pohint.po_flags |= MU_PARSEOPT_BUG_ADDRESS;
pohint.po_bug_address = va_arg (ap, char *);
+ if (pohint.po_bug_address)
+ pohint.po_flags |= MU_PARSEOPT_BUG_ADDRESS;
break;
case MU_CLI_OPTION_PACKAGE_NAME:
- pohint.po_flags |= MU_PARSEOPT_PACKAGE_NAME;
pohint.po_package_name = va_arg (ap, char *);
+ if (pohint.po_package_name)
+ pohint.po_flags |= MU_PARSEOPT_PACKAGE_NAME;
break;
case MU_CLI_OPTION_PACKAGE_URL:
- pohint.po_flags |= MU_PARSEOPT_PACKAGE_URL;
pohint.po_package_url = va_arg (ap, char *);
+ if (pohint.po_package_url)
+ pohint.po_flags |= MU_PARSEOPT_PACKAGE_URL;
break;
case MU_CLI_OPTION_EXTRA_INFO:
- pohint.po_flags |= MU_PARSEOPT_EXTRA_INFO;
pohint.po_extra_info = va_arg (ap, char *);
+ if (pohint.po_extra_info)
+ pohint.po_flags |= MU_PARSEOPT_EXTRA_INFO;
break;
case MU_CLI_OPTION_HELP_HOOK:
- pohint.po_flags |= MU_PARSEOPT_HELP_HOOK;
pohint.po_help_hook =
va_arg (ap, void (*) (struct mu_parseopt *, mu_stream_t));
+ if (pohint.po_help_hook)
+ pohint.po_flags |= MU_PARSEOPT_HELP_HOOK;
break;
case MU_CLI_OPTION_VERSION_HOOK:
- pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK;
pohint.po_version_hook =
va_arg (ap, void (*) (struct mu_parseopt *, mu_stream_t));
+ if (pohint.po_version_hook)
+ pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK;
break;
case MU_CLI_OPTION_PROG_DOC_HOOK:
- pohint.po_flags |= MU_PARSEOPT_PROG_DOC_HOOK;
pohint.po_prog_doc_hook =
va_arg (ap, void (*) (struct mu_parseopt *, mu_stream_t));
+ if (pohint.po_prog_doc_hook)
+ pohint.po_flags |= MU_PARSEOPT_PROG_DOC_HOOK;
break;
case MU_CLI_OPTION_NEGATION:
- pohint.po_flags |= MU_PARSEOPT_NEGATION;
pohint.po_negation = va_arg (ap, char *);
+ if (pohint.po_negation)
+ pohint.po_flags |= MU_PARSEOPT_NEGATION;
break;
case MU_CLI_OPTION_SPECIAL_ARGS:
- pohint.po_flags |= MU_PARSEOPT_SPECIAL_ARGS;
pohint.po_special_args = va_arg (ap, char *);
+ if (pohint.po_special_args)
+ pohint.po_flags |= MU_PARSEOPT_SPECIAL_ARGS;
break;
case MU_CLI_OPTION_CONF_SITE_FILE:
@@ -198,6 +209,11 @@ mu_cli_simple (int argc, char **argv, ...)
cfhint.flags |= MU_CFHINT_NO_CONFIG_OVERRIDE;
break;
+ case MU_CLI_OPTION_CONF_PROGNAME:
+ if ((cfhint.program = va_arg (ap, char *)) != NULL)
+ cfhint.flags |= MU_CFHINT_PROGRAM;
+ break;
+
default:
mu_diag_output (MU_DIAG_CRIT,
_("%s:%d: INTERNAL ERROR: unrecognized mu_cli_simple option"),
diff --git a/mu/libexec/Makefile.am b/mu/libexec/Makefile.am
index e94ebccc9..03bbb318d 100644
--- a/mu/libexec/Makefile.am
+++ b/mu/libexec/Makefile.am
@@ -83,6 +83,16 @@ if MU_COND_SUPPORT_IMAP
$(MUTOOL_LIBRARIES_TAIL)
endif
+if MU_COND_SUPPORT_MAILDIR
+ pkglibexec_PROGRAMS += mailutils-maildir_fixup
+ mailutils_maildir_fixup_SOURCES = maildir_fixup.c
+ mailutils_maildir_fixup_LDADD = \
+ $(MU_APP_LIBRARIES)\
+ $(MU_LIB_MAILDIR)\
+ $(MU_LIB_MAILUTILS)\
+ $(MUTOOL_LIBRARIES_TAIL)
+endif
+
mailutils_send_SOURCES = send.c
mailutils_send_CPPFLAGS = \
$(AM_CPPFLAGS)\
diff --git a/mu/libexec/maildir_fixup.c b/mu/libexec/maildir_fixup.c
new file mode 100644
index 000000000..811380691
--- /dev/null
+++ b/mu/libexec/maildir_fixup.c
@@ -0,0 +1,202 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2010-2020 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/>. */
+
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <mailutils/mailutils.h>
+#include <sysexits.h>
+#include "mu.h"
+#include "muaux.h"
+
+/* Utility-specific exit codes */
+enum
+ {
+ EXIT_OK, /* Success */
+ EXIT_HARDFAIL, /* None of the maildirs fixed */
+ EXIT_SOFTFAIL, /* Some of the maildirs failed to fix */
+ };
+
+static int verbose_option;
+static int dry_run_option;
+static unsigned long fail_count;
+static unsigned long succ_count;
+
+static struct mu_option options[] =
+{
+ { "verbose", 'v', NULL, MU_OPTION_DEFAULT,
+ "verbosely list what is being done",
+ mu_c_incr, &verbose_option },
+ { "dry-run", 'n', NULL, MU_OPTION_DEFAULT,
+ "do nothing, print everything",
+ mu_c_incr, &dry_run_option },
+ MU_OPTION_END
+};
+
+static int
+mailbox_fixup (void *item, void *data)
+{
+ struct mu_list_response *resp = item;
+ mu_mailbox_t mbox = NULL;
+ int rc;
+
+ if (!(resp->type & MU_FOLDER_ATTRIBUTE_FILE))
+ return 0;
+
+ if (verbose_option)
+ mu_diag_output (MU_DIAG_INFO, "Fixing %s", resp->name);
+ if (dry_run_option)
+ return 0;
+
+ rc = manlock_open_mailbox (&mbox, resp->name, 1, MU_STREAM_RDWR);
+ if (rc == 0)
+ {
+ rc = mu_mailbox_scan (mbox, 1, NULL);
+ mu_mailbox_close (mbox);
+ manlock_unlock (mbox);
+ mu_mailbox_destroy (&mbox);
+ }
+ else
+ mu_error ("can't open mailbox: %s", mu_strerror (rc));
+
+ if (rc)
+ fail_count++;
+ else
+ succ_count++;
+ return rc;
+}
+
+static inline int
+filename_ok (char const *fname)
+{
+ return fname[0] == '/' ||
+ fname[0] == '~' ||
+ (fname[0] == '.' &&
+ (fname[1] == '/' || (fname[1] == '.' && fname[2] == '/')));
+}
+
+static int
+fix_mailboxes_in_folder (char *fname)
+{
+ mu_folder_t folder;
+ struct mu_folder_scanner scn = MU_FOLDER_SCANNER_INITIALIZER;
+ int rc;
+
+ if (!filename_ok (fname))
+ {
+ char *cwd = mu_getcwd ();
+ size_t prefix_len = strlen (cwd);
+ if (cwd[prefix_len-1] != '/')
+ prefix_len++;
+ fname = mu_make_file_name (cwd, fname);
+ free (cwd);
+ if (!fname)
+ mu_alloc_die ();
+ }
+
+ rc = mu_folder_create (&folder, fname);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc);
+ return rc;
+ }
+ rc = mu_folder_open (folder, MU_STREAM_READ);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc);
+ goto err;
+ }
+
+ rc = mu_list_create (&scn.result);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, rc);
+ goto err;
+ }
+
+ rc = mu_folder_scan (folder, &scn);
+ if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_scan", NULL, rc);
+ else
+ mu_list_foreach (scn.result, mailbox_fixup, NULL);
+
+ err:
+ mu_list_destroy (&scn.result);
+ mu_folder_destroy (&folder);
+ return rc;
+}
+
+static char docstring[] = N_(
+ "recursively scans all maildirs in the folder\n"
+ "\nThis induces fixing of the maildir message attributes (bug #56428) "
+ "and attaching persistent UID numbers (commits fd9b19bac-d7110faa).\n"
+);
+static char argdoc[] = N_("FOLDER ...");
+static char *capa[] = {
+ "debug",
+ "locking",
+ NULL
+};
+
+static struct mu_cfg_param config_param[] = {
+ { "mandatory-locking", mu_cfg_section },
+ { NULL }
+};
+
+int
+main (int argc, char **argv)
+{
+ int i;
+
+ mu_registrar_record (mu_maildir_record);
+ mu_registrar_set_default_scheme ("maildir");
+ manlock_cfg_init ();
+ mu_cli_simple (argc, argv,
+ MU_CLI_OPTION_OPTIONS, options,
+ MU_CLI_OPTION_OPTIONS, common_options,
+ MU_CLI_OPTION_PROG_NAME, getenv ("MAILUTILS_PROGNAME"),
+ MU_CLI_OPTION_PROG_DOC, docstring,
+ MU_CLI_OPTION_PROG_ARGS, argdoc,
+ MU_CLI_OPTION_RETURN_ARGC, &argc,
+ MU_CLI_OPTION_RETURN_ARGV, &argv,
+ MU_CLI_OPTION_PACKAGE_NAME, PACKAGE_NAME,
+ MU_CLI_OPTION_PACKAGE_URL, PACKAGE_URL,
+ MU_CLI_OPTION_BUG_ADDRESS, PACKAGE_BUGREPORT,
+ MU_CLI_OPTION_VERSION_HOOK, mu_version_hook,
+ MU_CLI_OPTION_CAPABILITIES, capa,
+ MU_CLI_OPTION_CONFIG, config_param,
+ MU_CLI_OPTION_CONF_SITE_FILE, NULL,
+ MU_CLI_OPTION_CONF_PROGNAME, "maildir_fixup",
+ MU_CLI_OPTION_END);
+
+ if (argc == 0)
+ {
+ mu_error ("required argument missing; try --help for more info");
+ exit (EX_USAGE);
+ }
+
+ if (dry_run_option)
+ verbose_option++;
+
+ for (i = 0; i < argc; i++)
+ fix_mailboxes_in_folder (argv[i]);
+
+ if (fail_count)
+ exit (succ_count == 0 ? EXIT_HARDFAIL : EXIT_SOFTFAIL);
+
+ exit (EXIT_OK);
+}
+
diff --git a/mu/libexec/mu.h b/mu/libexec/mu.h
index 7631728f3..8050ce3e0 100644
--- a/mu/libexec/mu.h
+++ b/mu/libexec/mu.h
@@ -21,6 +21,7 @@
#include <stdarg.h>
#include <mailutils/mailutils.h>
+extern struct mu_option common_options[];
void mu_action_getopt (int *pargc, char ***pargv, struct mu_option *opt,
char const *docstring, char const *argdoc);
int mu_vgetans (const char *variants, const char *fmt, va_list ap);

Return to:

Send suggestions and report system problems to the System administrator.