summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2003-03-15 23:19:49 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2003-03-15 23:19:49 +0000
commitc8463abee101ad757691e6e2c4e0e5ab25873a17 (patch)
tree5d509d4f8047e4a7711400364cc13d0ec68121a9
parent45a1e5a5e9d549cea3f3eda1d719838e71ba9f0e (diff)
downloadmailutils-c8463abee101ad757691e6e2c4e0e5ab25873a17.tar.gz
mailutils-c8463abee101ad757691e6e2c4e0e5ab25873a17.tar.bz2
Implementation of mhn utility
-rw-r--r--mh/mhn.c871
1 files changed, 871 insertions, 0 deletions
diff --git a/mh/mhn.c b/mh/mhn.c
new file mode 100644
index 000000000..51a61c043
--- /dev/null
+++ b/mh/mhn.c
@@ -0,0 +1,871 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2003 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 2, 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* MH mhn command */
+
+#include <mh.h>
+
+const char *argp_program_version = "mhn (" PACKAGE_STRING ")";
+static char doc[] = N_("GNU MH mhn\v"
+"Options marked with `*' are not yet implemented.\n"
+"Use -help to obtain the list of traditional MH options.");
+static char args_doc[] = "[msgs]";
+
+static struct argp_option options[] = {
+ {"folder", ARG_FOLDER, N_("FOLDER"), 0,
+ N_("Specify folder to operate upon"), 0},
+ {"file", ARG_FILE, N_("FILE"), 0,
+ N_("Specify file to operate upon"), 0},
+
+ {N_("MIME editing options"), 0, NULL, OPTION_DOC, NULL, 5},
+ {"compose", ARG_COMPOSE, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("* Compose the MIME message (default)"), 6},
+ {"nocompose", ARG_NOCOMPOSE, NULL, OPTION_HIDDEN, "", 6},
+
+ {N_("Listing options"), 0, NULL, OPTION_DOC, NULL, 0},
+ {"list", ARG_LIST, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("List the table of contents"), 11 },
+ {"nolist", ARG_NOLIST, NULL, OPTION_HIDDEN, "", 11 },
+ {"headers", ARG_HEADER, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("Print the banner above the listing"), 12},
+ {"noheaders", ARG_NOHEADERS, NULL, OPTION_HIDDEN, "", 12 },
+ {"realsize", ARG_REALSIZE, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("List the decoded sizes"), 12},
+ {"norealsize", ARG_NOREALSIZE, NULL, OPTION_HIDDEN, "", 12 },
+
+ {N_("Display options"), 0, NULL, OPTION_DOC, NULL, 20},
+ {"show", ARG_SHOW, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("Display the contents of the messages"), 21},
+ {"noshow", ARG_NOSHOW, NULL, OPTION_HIDDEN, "", 21 },
+ {"serialonly", ARG_SERIALONLY, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("* Display messages serially"), 22},
+ {"noserialonly", ARG_NOSERIALONLY, NULL, OPTION_HIDDEN, "", 22 },
+ {"form", ARG_FORM, N_("FILE"), 0,
+ N_("Read mhl format from FILE"), 22},
+ {"pause", ARG_PAUSE, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("* Pause prior to displaying content"), 22},
+ {"nopause", ARG_NOPAUSE, NULL, OPTION_HIDDEN, "", 22 },
+
+ {N_("Saving options"), 0, NULL, OPTION_DOC, NULL, 30},
+ {"store", ARG_STORE, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("* Store the contents of the messages on disk"), 31},
+ {"nostore", ARG_NOSTORE, NULL, OPTION_HIDDEN, "", 31 },
+ {"auto", ARG_AUTO, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("* Use filenames from the content headers"), 31},
+ {"noauto", ARG_NOAUTO, NULL, OPTION_HIDDEN, "", 31 },
+
+ {N_("Other options"), 0, NULL, OPTION_DOC, NULL, 40},
+ {"part", ARG_PART, N_("PART"), 0,
+ N_("Limit the scope of the operation to the given part"), 41},
+ {"type", ARG_TYPE, N_("CONTENT"), 0,
+ N_("Operate on message part with given multipart content"), 41 },
+ {"verbose", ARG_VERBOSE, N_("BOOL"), OPTION_ARG_OPTIONAL,
+ N_("Print additional information"), 41 },
+ {"noverbose", ARG_NOVERBOSE, NULL, OPTION_HIDDEN, "", 41 },
+ {NULL}
+};
+
+/* Traditional MH options */
+struct mh_option mh_option[] = {
+ {"file", 2, 0, "filename"},
+ {"list", 1, MH_OPT_BOOL, NULL},
+ {"headers", 1, MH_OPT_BOOL, NULL},
+ {"realsize", 1, MH_OPT_BOOL, NULL},
+ {"show", 2, MH_OPT_BOOL, NULL},
+ {"serialonly", 2, MH_OPT_BOOL, NULL},
+ {"form", 2, 0, "formfile"},
+ {"pause", 3, MH_OPT_BOOL, NULL},
+ {"store", 1, MH_OPT_BOOL, NULL},
+ {"auto", 1, MH_OPT_BOOL, NULL},
+ {"part", 3, 0, "part"},
+ {"type", 1, 0, "type"},
+ {"verbose", 1, MH_OPT_BOOL, NULL},
+ {NULL}
+};
+
+typedef struct _msg_part *msg_part_t;
+
+static msg_part_t msg_part_create __P((size_t num));
+static void msg_part_destroy __P((msg_part_t p));
+static int msg_part_eq __P((msg_part_t a, msg_part_t b));
+static void msg_part_incr __P((msg_part_t p));
+static void msg_part_decr __P((msg_part_t p));
+static void msg_part_set_subpart __P((msg_part_t p, size_t subpart));
+static void msg_part_print __P((msg_part_t p, int width));
+static msg_part_t msg_part_parse __P((char *str));
+static int msg_part_level __P((msg_part_t p));
+static size_t msg_part_subpart __P((msg_part_t p, int level));
+
+enum mhn_mode {
+ mode_compose,
+ mode_list,
+ mode_show,
+ mode_store,
+};
+
+static enum mhn_mode mode = mode_compose;
+
+#define OPT_HEADERS 001
+#define OPT_REALSIZE 002
+#define OPT_PAUSE 004
+#define OPT_AUTO 010
+#define OPT_SERIALONLY 020
+#define OPT_VERBOSE 040
+
+static int mode_options = OPT_HEADERS;
+static char *formfile;
+static char *content_type;
+static char *content_subtype;
+static char *input_file;
+static int width = 80;
+
+static mh_msgset_t msgset;
+static mailbox_t mbox;
+static message_t message;
+static msg_part_t req_part;
+
+void
+sfree (char **ptr)
+{
+ if (!*ptr)
+ return;
+ free (*ptr);
+ *ptr = NULL;
+}
+
+void
+split_content (const char *content, char **type, char **subtype)
+{
+ char *p = strchr (content, '/');
+ if (p)
+ {
+ int len = p - content;
+ *type = xmalloc (len + 1);
+ memcpy (*type, content, len);
+ (*type)[len] = 0;
+
+ p++;
+ *subtype = xmalloc (strlen (p) + 1);
+ strcpy (*subtype, p);
+ }
+ else
+ {
+ *type = xmalloc (strlen (content) + 1);
+ strcpy (*type, content);
+ *subtype = NULL;
+ }
+}
+
+static int
+opt_handler (int key, char *arg, void *unused, struct argp_state *state)
+{
+ switch (key)
+ {
+ case ARG_FOLDER:
+ current_folder = arg;
+ break;
+
+ case ARG_FILE:
+ input_file = arg;
+ break;
+
+ /* Operation mode */
+ case ARG_COMPOSE:
+ if (is_true (arg))
+ {
+ mode = mode_compose;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOCOMPOSE:
+ if (mode == mode_compose)
+ mode = mode_compose;
+ break;
+
+ case ARG_LIST:
+ if (is_true (arg))
+ {
+ mode = mode_list;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOLIST:
+ if (mode == mode_list)
+ mode = mode_compose;
+ break;
+
+ case ARG_SHOW:
+ if (is_true (arg))
+ {
+ mode = mode_show;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOSHOW:
+ if (mode == mode_show)
+ mode = mode_compose;
+ break;
+
+ case ARG_STORE:
+ if (is_true (arg))
+ {
+ mode = mode_store;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOSTORE:
+ if (mode == mode_store)
+ mode = mode_compose;
+ break;
+
+ /* List options */
+ case ARG_HEADER:
+ if (is_true (arg))
+ {
+ mode_options |= OPT_HEADERS;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOHEADERS:
+ mode_options &= ~OPT_HEADERS;
+ break;
+
+ case ARG_REALSIZE:
+ if (is_true (arg))
+ {
+ mode_options |= OPT_REALSIZE;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOREALSIZE:
+ mode_options &= ~OPT_REALSIZE;
+ break;
+
+ /* Display options */
+
+ case ARG_SERIALONLY:
+ if (is_true (arg))
+ {
+ mode_options |= OPT_SERIALONLY;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOSERIALONLY:
+ mode_options &= ~OPT_SERIALONLY;
+ break;
+
+ case ARG_PAUSE:
+ if (is_true (arg))
+ {
+ mode_options |= OPT_PAUSE;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOPAUSE:
+ mode_options &= ~OPT_PAUSE;
+ break;
+
+ /* Store options */
+ case ARG_AUTO:
+ if (is_true (arg))
+ {
+ mode_options |= OPT_AUTO;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOAUTO:
+ mode_options &= ~OPT_AUTO;
+ break;
+
+ case ARG_FORM:
+ formfile = arg;
+ break;
+
+ /* Common options */
+ case ARG_VERBOSE:
+ if (is_true (arg))
+ {
+ mode_options |= OPT_VERBOSE;
+ break;
+ }
+ /*FALLTHRU*/
+ case ARG_NOVERBOSE:
+ mode_options &= ~OPT_VERBOSE;
+ break;
+
+ case ARG_TYPE:
+ sfree (&content_type);
+ sfree (&content_subtype);
+ split_content (arg, &content_type, &content_subtype);
+ break;
+
+ case ARG_PART:
+ req_part = msg_part_parse (arg);
+ break;
+
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+
+/* *********************** Message part functions ************************* */
+
+struct _msg_part {
+ int level;
+ int maxlevel;
+ size_t *part;
+};
+
+msg_part_t
+msg_part_create (size_t num)
+{
+ msg_part_t p = xmalloc (sizeof (*p));
+ p->maxlevel = 16;
+ p->part = xmalloc (sizeof (*p->part) * p->maxlevel);
+ p->part[0] = num;
+ p->level = 0;
+ return p;
+}
+
+void
+msg_part_destroy (msg_part_t p)
+{
+ free (p->part);
+ free (p);
+}
+
+int
+msg_part_eq (msg_part_t a, msg_part_t b)
+{
+ int i, level = a->level < b->level ? a->level : b->level;
+
+ for (i = 1; i <= level; i++)
+ if (a->part[i] != b->part[i])
+ return 1;
+ return 0;
+}
+
+void
+msg_part_incr (msg_part_t p)
+{
+ if (p->level == p->maxlevel)
+ {
+ p->maxlevel += 16;
+ p->part = xrealloc (p->part, sizeof (*p->part) * p->maxlevel);
+ }
+ p->level++;
+}
+
+void
+msg_part_decr (msg_part_t p)
+{
+ if (p->level <= 0)
+ abort ();
+ p->level--;
+}
+
+void
+msg_part_set_subpart (msg_part_t p, size_t subpart)
+{
+ p->part[p->level] = subpart;
+}
+
+void
+msg_part_print (msg_part_t p, int max_width)
+{
+ int i;
+ int width = 0;
+
+ for (i = 1; i <= p->level; i++)
+ {
+ if (i > 1)
+ {
+ printf (".");
+ width++;
+ }
+ width += printf ("%lu", (unsigned long) p->part[i]);
+ }
+ for (; width < max_width; width++)
+ putchar (' ');
+}
+
+msg_part_t
+msg_part_parse (char *str)
+{
+ msg_part_t p = msg_part_create (0);
+
+ do
+ {
+ char *endp;
+ size_t num = strtoul (str, &endp, 10);
+
+ switch (*endp)
+ {
+ case '.':
+ str = endp + 1;
+ break;
+ case 0:
+ str = endp;
+ break;
+ default:
+ mh_error (_("malformed part specification (near %s)"), endp);
+ exit (1);
+ }
+ msg_part_incr (p);
+ msg_part_set_subpart (p, num);
+ }
+ while (*str);
+ return p;
+}
+
+int
+msg_part_level (msg_part_t p)
+{
+ return p->level;
+}
+
+size_t
+msg_part_subpart (msg_part_t p, int level)
+{
+ if (level <= p->level)
+ return p->part[level];
+ return 0;
+}
+
+
+/* ************************** Message iterators *************************** */
+
+int
+_get_hdr_value (header_t hdr, const char *name, char **value)
+{
+ int status = header_aget_value (hdr, name, value);
+ if (status == 0)
+ {
+ /* Remove the newlines. */
+ char *nl;
+ while ((nl = strchr (*value, '\n')) != NULL)
+ *nl = ' ';
+ }
+ return status;
+}
+
+int
+_get_content_type (header_t hdr, char **value)
+{
+ char *type = NULL;
+ _get_hdr_value (hdr, MU_HEADER_CONTENT_TYPE, &type);
+ if (type == NULL || *type == '\0')
+ {
+ if (type)
+ free (type);
+ type = strdup ("text/plain"); /* Default. */
+ }
+ else
+ {
+ char *p = strchr (type, ';');
+ if (p)
+ *p = 0;
+ }
+ *value = type;
+ return 0;
+}
+
+static int
+_get_content_encoding (header_t hdr, char **value)
+{
+ char *encoding = NULL;
+ _get_hdr_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING, &encoding);
+ if (encoding == NULL || *encoding == '\0')
+ {
+ if (encoding)
+ free (encoding);
+ encoding = strdup ("7bit"); /* Default. */
+ }
+ *value = encoding;
+ return 0;
+}
+
+typedef int (*msg_handler_t) __PMT((message_t msg, msg_part_t part,
+ char *type, char *encoding,
+ void *data));
+
+int
+match_content (char *content)
+{
+ int rc;
+ char *type, *subtype;
+
+ if (!content_type && !content_subtype)
+ return 0;
+ if (!content)
+ return 0;
+
+ split_content (content, &type, &subtype);
+
+ if (strcasecmp (content_type, type) == 0)
+ rc = strcasecmp (content_subtype, subtype);
+ else
+ rc = strcasecmp (content_type, subtype);
+
+ free (type);
+ free (subtype);
+ return rc;
+}
+
+int
+call_handler (message_t msg, msg_part_t part, char *type, char *encoding,
+ msg_handler_t fun, void *data)
+{
+ if (req_part && msg_part_eq (req_part, part))
+ return 0;
+ if (match_content (type))
+ return 0;
+ return fun (msg, part, type, encoding, data);
+}
+
+int
+handle_message (message_t msg, msg_part_t part, msg_handler_t fun, void *data)
+{
+ header_t hdr;
+ char *type = NULL;
+ char *encoding;
+ int ismime = 0;
+
+ message_get_header (msg, &hdr);
+ _get_content_type (hdr, &type);
+ _get_content_encoding (hdr, &encoding);
+
+ fun (msg, part, type, encoding, data);
+ sfree (&type);
+ sfree (&encoding);
+
+ message_is_multipart (msg, &ismime);
+ if (ismime)
+ {
+ unsigned int i, nparts;
+
+ message_get_num_parts (msg, &nparts);
+
+ msg_part_incr (part);
+ for (i = 1; i <= nparts; i++)
+ {
+ message_t message = NULL;
+
+ if (message_get_part (msg, i, &message) == 0)
+ {
+ message_get_header (message, &hdr);
+ _get_content_type (hdr, &type);
+ _get_content_encoding (hdr, &encoding);
+
+ msg_part_set_subpart (part, i);
+
+ if (strcasecmp (type, "multipart/mixed") == 0)
+ handle_message (message, part, fun, data);
+ else
+ call_handler (message, part, type, encoding, fun, data);
+ sfree (&type);
+ sfree (&encoding);
+ }
+ }
+ msg_part_decr (part);
+ }
+ return 0;
+}
+
+int
+mhn_message_size (message_t msg, size_t *psize)
+{
+ body_t body;
+ *psize = 0;
+ message_get_body (msg, &body);
+ if (mode_options & OPT_REALSIZE)
+ {
+ stream_t dstr = NULL, bstr = NULL;
+
+ if (body_get_stream (body, &bstr) == 0)
+ {
+ header_t hdr;
+ char *encoding;
+ size_t size = 0;
+ int rc;
+
+ message_get_header (msg, &hdr);
+ _get_content_encoding (hdr, &encoding);
+
+ rc = filter_create(&dstr, bstr, encoding,
+ MU_FILTER_DECODE, MU_STREAM_READ);
+ free (encoding);
+ if (rc == 0)
+ {
+ char buf[512];
+ size_t n;
+
+ while (stream_sequential_read (dstr, buf, sizeof buf, &n) == 0
+ && n > 0)
+ size += n;
+
+ stream_destroy (&dstr, NULL);
+ *psize = size;
+ return 0;
+ }
+ }
+ }
+
+ return body_size (body, psize);
+}
+
+
+/* ***************************** List Mode ******************************* */
+
+int
+list_handler (message_t msg, msg_part_t part, char *type, char *encoding,
+ void *data)
+{
+ size_t size;
+ header_t hdr;
+
+ if (msg_part_level (part) == 0)
+ printf ("%3lu ", (unsigned long) msg_part_subpart (part, 0));
+ else
+ {
+ printf (" ");
+ msg_part_print (part, 5);
+ putchar (' ');
+ }
+ printf ("%-26s", type);
+
+ mhn_message_size (msg, &size);
+ printf ("%4lu", (unsigned long) size);
+
+ if (message_get_header (msg, &hdr) == 0)
+ {
+ char *descr;
+ if (header_aget_value (hdr, "Content-Description", &descr) == 0)
+ {
+ printf (" %s", descr);
+ free (descr);
+ }
+ }
+
+ printf ("\n");
+ return 0;
+}
+
+int
+list_message (message_t msg, size_t num)
+{
+ msg_part_t part = msg_part_create (num);
+ handle_message (msg, part, list_handler, NULL);
+ msg_part_destroy (part);
+ return 0;
+}
+
+void
+list_iterator (mailbox_t mbox, message_t msg, size_t num, void *data)
+{
+ list_message (msg, num);
+}
+
+int
+mhn_list ()
+{
+ int rc;
+
+ if (mode_options & OPT_HEADERS)
+ printf (_("msg part type/subtype size description\n"));
+
+ if (message)
+ rc = list_message (message, 0);
+ else
+ rc = mh_iterate (mbox, &msgset, list_iterator, NULL);
+ return rc;
+}
+
+
+/* ***************************** Show Mode ******************************* */
+
+static list_t mhl_format;
+
+void
+cat_message (stream_t out, stream_t in)
+{
+ int rc = 0;
+ char buf[512];
+ size_t n;
+
+ stream_seek (in, 0, SEEK_SET);
+ while (rc == 0
+ && stream_sequential_read (in, buf, sizeof buf, &n) == 0
+ && n > 0)
+ rc = stream_sequential_write (out, buf, n);
+}
+
+int
+show_handler (message_t msg, msg_part_t part, char *type, char *encoding,
+ void *data)
+{
+ stream_t out = data;
+
+ if (strncasecmp (type, "multipart", 9) == 0)
+ return 0;
+ if (mhl_format)
+ mhl_format_run (mhl_format, width, 0, MHL_DECODE, msg, out);
+ else
+ {
+ int rc;
+ body_t body = NULL;
+ stream_t dstr, bstr;
+
+ if ((rc = message_get_body (msg, &body)))
+ {
+ mh_error (_("%lu: can't get message body: %s"),
+ (unsigned long) msg_part_subpart (part, 0),
+ mu_strerror (rc));
+ return 0;
+ }
+ body_get_stream (body, &bstr);
+ rc = filter_create(&dstr, bstr, encoding,
+ MU_FILTER_DECODE, MU_STREAM_READ);
+ if (rc == 0)
+ bstr = dstr;
+ cat_message (out, bstr);
+ if (dstr)
+ stream_destroy (&dstr, stream_get_owner (dstr));
+ }
+}
+
+int
+show_message (message_t msg, size_t num, void *data)
+{
+ msg_part_t part = msg_part_create (num);
+ handle_message (msg, part, show_handler, data);
+ msg_part_destroy (part);
+ return 0;
+}
+
+void
+show_iterator (mailbox_t mbox, message_t msg, size_t num, void *data)
+{
+ show_message (msg, num, data);
+}
+
+int
+mhn_show ()
+{
+ int rc;
+ stream_t ostr;
+
+ rc = stdio_stream_create (&ostr, stdout, 0);
+ if (rc)
+ {
+ mh_error (_("can't create output stream: %s"), mu_strerror (rc));
+ exit (1);
+ }
+ rc = stream_open (ostr);
+ if (rc)
+ {
+ mh_error (_("can't open output stream: %s"), mu_strerror (rc));
+ exit (1);
+ }
+
+ if (formfile)
+ {
+ char *s = mh_expand_name (MHLIBDIR, "mhl.headers", 0);
+ if (access (s, R_OK) == 0)
+ formfile = "mhl.headers";
+ free (s);
+ }
+
+ if (formfile)
+ {
+ char *s = mh_expand_name (MHLIBDIR, formfile, 0);
+ mhl_format = mhl_format_compile (s);
+ if (!mhl_format)
+ exit (1);
+ free (s);
+ }
+
+ if (message)
+ rc = show_message (message, 0, ostr);
+ else
+ rc = mh_iterate (mbox, &msgset, show_iterator, ostr);
+ return rc;
+}
+
+
+
+/* *************************** Main Entry Point ************************** */
+
+int
+main (int argc, char **argv)
+{
+ int rc;
+ int index;
+
+ mu_init_nls ();
+
+ mh_argp_parse (argc, argv, 0, options, mh_option, args_doc, doc,
+ opt_handler, NULL, &index);
+
+ argc -= index;
+ argv += index;
+
+ if (input_file)
+ {
+ if (argc)
+ {
+ mh_error (_("extra arguments"));
+ return 1;
+ }
+ message = mh_file_to_message (mu_path_folder_dir, input_file);
+ if (!message)
+ return 1;
+ }
+ else
+ {
+ mbox = mh_open_folder (current_folder, 0);
+ mh_msgset_parse (mbox, &msgset, argc, argv, "cur");
+ }
+
+ switch (mode)
+ {
+ case mode_compose:
+ mh_error ("mode is not yet implemented");
+ rc = 1;
+ break;
+
+ case mode_list:
+ rc = mhn_list ();
+ break;
+
+ case mode_show:
+ rc = mhn_show ();
+ break;
+
+ case mode_store:
+ mh_error ("mode is not yet implemented");
+ rc = 1;
+ break;
+
+ default:
+ abort ();
+ }
+ return rc ? 1 : 0;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.