summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-07-12 18:09:57 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-07-12 18:09:57 +0300
commit0a7e59334332346755a05df5f85aafdba629d78d (patch)
tree178e39495c7165e4d119a9b3b1f6f07f9750138e
parent61295ae0e724c62ac016dfc374d6064c63270288 (diff)
downloadmailutils-0a7e59334332346755a05df5f85aafdba629d78d.tar.gz
mailutils-0a7e59334332346755a05df5f85aafdba629d78d.tar.bz2
Improve mail compliance to POSIX standard
* mail/mail.c: Redo -f option handling to fully comply to POSIX Set default diagnostics printer for interactive mode. * NEWS, doc/texinfo/programs.texi: Document the use of -f option.
-rw-r--r--NEWS21
-rw-r--r--doc/texinfo/programs.texi65
-rw-r--r--mail/mail.c160
3 files changed, 154 insertions, 92 deletions
diff --git a/NEWS b/NEWS
index 29bb08a02..861058b26 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2009-07-11
+GNU mailutils NEWS -- history of user-visible changes. 2009-07-12
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009 Free Software Foundation, Inc.
See the end of file for copying conditions.
@@ -29,6 +29,25 @@ information.
* Mail
+** The -f option
+
+The semantics of -f (--file) option fully complies to the POSIX
+standard. Namely, this option instructs mail to read messages
+from the file named by the first non-optional command line
+argument. Therefore, the following four usage patterns are
+entirely equivalent:
+
+ mail -fin mymbox
+ mail -f mymbox -in
+ mail --file -in mymbox
+ mail --file -i mymbox -n
+
+In addition, the form
+
+ mail --file=mymbox
+
+is also allowed.
+
** envelope command
The env[elope] command displays the SMTP envelopes of the messages
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index 1c21a5257..0267fd850 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -2189,9 +2189,8 @@ See @ref{Composing Mail}, for a detailed description of this behavior.
If the command line contained no email addresses, @command{mail} switches
to reading mode. In this mode it allows to read and manipulate the
-contents of a mailbox. The URL of the mailbox to operate upon is
-taken from the argument of @option{--file} command line option. If it
-is not specified, the user's system mailbox is assumed. For more
+contents of the user system mailbox. The @option{--file} (@option{-f})
+command line option allows to specify another mailbox name. For more
detail, see @ref{Reading Mail}.
In contrast to other GNU Mailutils programs, @command{mail} does not
@@ -2237,16 +2236,12 @@ Execute @var{command} before opening the mailbox. Any number of
@option{--exec} options can be given. The commands will be executed
after sourcing configuration files (@pxref{Mail Configuration Files}),
but before opening the mailbox.
-@item --exec
-@item -f[@var{file}]
-@itemx --file[=@var{file}]
-Operate on mailbox @var{file}. If this option is not specified, the default
-is user's system mailbox. If it is specified without argument, the
-default is @file{$HOME/mbox}.
-@emph{Please note}, that there should be no whitespace between the
-short variant of the option (@option{-f}), and its parameter. Similarly,
-when using long option (@option{--file}), its argument must be preceded by
-equal sign.
+@item -f
+@itemx --file
+Operate on the mailbox given by the first non-optional command line
+argument. If there is no such argument, read messages from the
+user's @file{mbox} file. @xref{Reading Mail} for more details about
+using this option.
@item -F
@itemx --byname
Save messages according to sender. Currently this option is not implemented.
@@ -2628,10 +2623,15 @@ invoking @command{mail}:
@table @code
@item mail
To read messages from your system mailbox.
-@item mail --file
-To read messages from your mailbox (@file{$HOME/mbox}).
-@item mail --file=@var{path_to_mailbox}
+@item mail -f
+@itemx mail --file
+To read messages from your mailbox (@file{$HOME/mbox}). If the
+@option{--user} option (see below) is also given, read messages
+from that user's @file{mbox}.
+@item mail -f @var{path_to_mailbox}
+@itemx mail --file @var{path_to_mailbox}
To read messages from the specified mailbox.
+@itemx mail -u @var{user}
@item mail --user=@var{user}
To read messages from the system mailbox belonging to @var{user}.
@end table
@@ -2641,6 +2641,25 @@ to use the last variant of invocation, unless you are a super-user.
Similarly, the last but one variant is also greatly affected by the
permissions the target mailbox has.
+Notice that @var{path_to_mailbox} is not an argument to
+@option{--file} (@option{-f}) option, but rather the first
+non-optional argument on the command line. Therefore, the
+following three invocations are equivalent:
+
+@smallexample
+$ mail -fin mymbox
+$ mail -f mymbox -in
+$ mail --file -in mymbox
+$ mail --file -i mymbox -n
+@end smallexample
+
+Additionally, for conformance to the GNU standards, the
+following form is also accepted:
+
+@smallexample
+$ mail --file=mymbox -i -n
+@end smallexample
+
Unless you have started mail with @option{--norc} command line option,
it will read the contents of the system-wide configuration file.
Then it reads the contents of user configuration file, if any.
@@ -3563,6 +3582,20 @@ if @code{crt} is set without a value, then the height of the terminal
screen is used to compute the threshold. The number of lines on
screen is controlled by @code{screen} variable.
+@item debug
+@*Type: String to boolean
+@*Default: Not set
+@vrindex debug, mail variable
+
+Sets mailutils debug level. If set to string, the value must be a
+valid Mailutils debugging specification. @xref{Debug Statement}, for
+a description.
+
+If unset (i.e. @code{set nodebug}), clears and disables all debugging
+information. If set to @samp{true} (i.e. @code{set debug}), sets
+maximum debugging (@samp{<trace7}) on mailbox and its underlying
+objects.
+
@item decode-fallback
@*Type: String.
@*Default: @samp{none}.
diff --git a/mail/mail.c b/mail/mail.c
index ff98d9cb5..7fe8a6960 100644
--- a/mail/mail.c
+++ b/mail/mail.c
@@ -30,13 +30,18 @@ static mu_list_t command_list; /* List of commands to be executed after parsin
command line */
const char *program_version = "mail (" PACKAGE_STRING ")";
-static char doc[] = N_("GNU mail -- the standard /bin/mail interface");
-static char args_doc[] = N_("[address...]");
+static char doc[] = N_("GNU mail -- process mail messages.\n"
+"If -f or --file is given, mail operates on the mailbox named "
+"by the first argument, or the user's mbox, if no argument given.\n");
+static char args_doc[] = N_("[address...]\n-f [OPTION...] [file]\n--file [OPTION...] [file]\n--file=file [OPTION...]");
+
+#define F_OPTION 256
static struct argp_option options[] = {
+ { NULL, 'f', 0, OPTION_HIDDEN, NULL, 0 },
+ {"file", F_OPTION, "FILE", OPTION_ARG_OPTIONAL|OPTION_HIDDEN, 0},
+
{"exist", 'e', 0, 0, N_("Return true if mail exists"), 0},
- {"file", 'f', N_("URL"), OPTION_ARG_OPTIONAL,
- N_("Operate on given mailbox URL (default ~/mbox)"), 0},
{"byname", 'F', 0, 0, N_("Save messages according to sender"), 0},
{"headers", 'H', 0, 0, N_("Write a header summary and exit"), 0},
{"ignore", 'i', 0, 0, N_("Ignore interrupts"), 0},
@@ -56,12 +61,16 @@ static struct argp_option options[] = {
};
+#define HINT_SEND_MODE 0x1
+#define HINT_FILE_OPTION 0x2
+
struct arguments
{
- char **args;
+ int argc;
+ char **argv;
char *file;
char *user;
- int send_mode;
+ int hint;
};
static error_t
@@ -72,32 +81,20 @@ parse_opt (int key, char *arg, struct argp_state *state)
switch (key)
{
case 'a':
- args->send_mode = 1;
+ args->hint |= HINT_SEND_MODE;
send_append_header (arg);
break;
case 'e':
util_cache_command (&command_list, "setq mode=exist");
break;
-
- case 'f':
- if (arg != NULL)
+
+ case F_OPTION:
+ if (arg)
args->file = arg;
- /* People often tend to separate -f option from its argument
- with a whitespace. This heuristics tries to catch the
- error: */
- else if (state->next < state->argc
- && state->argv[state->next][0] != '-')
- args->file = state->argv[state->next++];
- else
- {
- int len;
- char *home = getenv("HOME");
- len = strlen (home) + strlen ("/mbox") + 1;
- args->file = xmalloc(len * sizeof (char));
- strcpy (args->file, home);
- strcat (args->file, "/mbox");
- }
+ /* fall through */
+ case 'f':
+ args->hint |= HINT_FILE_OPTION;
break;
case 'p':
@@ -130,9 +127,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case 's':
+ args->hint |= HINT_SEND_MODE;
send_append_header2 (MU_HEADER_SUBJECT, arg, COMPOSE_REPLACE);
util_cache_command (&command_list, "set noasksub");
- args->send_mode = 1;
break;
case 'u':
@@ -149,15 +146,39 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case ARGP_KEY_ARG:
- args->args = realloc (args->args,
+ args->argv = realloc (args->argv,
sizeof (char *) * (state->arg_num + 2));
- args->args[state->arg_num] = arg;
- args->args[state->arg_num + 1] = NULL;
- args->send_mode = 1;
+ args->argv[state->arg_num] = arg;
+ args->argv[state->arg_num + 1] = NULL;
+ args->argc = state->arg_num + 1;
break;
case ARGP_KEY_FINI:
- if (args->send_mode)
+ if ((args->hint & (HINT_SEND_MODE|HINT_FILE_OPTION)) ==
+ (HINT_SEND_MODE|HINT_FILE_OPTION))
+ argp_error (state, _("conflicting options"));
+ else if (args->hint & HINT_FILE_OPTION)
+ {
+ if (args->file)
+ {
+ if (args->argc > 1)
+ argp_error (state,
+ _("-f requires at most one command line argument"));
+ }
+ else if (args->argc)
+ {
+ args->file = args->argv[0];
+
+ if (args->argc > 1)
+ argp_error (state,
+ _("-f requires at most one command line argument"));
+ }
+ else if (args->user)
+ asprintf (&args->file, "~/%s/mbox", args->user);
+ else
+ args->file = "~/mbox";
+ }
+ else if (args->argc || (args->hint & HINT_SEND_MODE))
util_cache_command (&command_list, "setq mode=send");
break;
@@ -230,7 +251,7 @@ static char *default_setup[] = {
"set noautoprint",
"set nobang",
"set nocmd",
- "set nodebug",
+ /* "set nodebug",*/
"set nodot",
"set escape=~",
"set noflipr",
@@ -281,11 +302,19 @@ static char *default_setup[] = {
"set nullbodymsg=\"" N_("Null message body; hope that's ok") "\"",
/* These settings are not yet used */
- "set nodebug",
"set noonehop",
"set nosendwait",
};
+static int
+mail_diag_stderr_printer (void *data, mu_log_level_t level, const char *buf)
+{
+ if (level != MU_DIAG_ERROR)
+ fprintf (stderr, "%s: ", mu_diag_level_to_string (level));
+ fputs (buf, stderr);
+ return 0;
+}
+
int
main (int argc, char **argv)
{
@@ -345,14 +374,15 @@ main (int argc, char **argv)
char *mailer_name = alloca (strlen ("sendmail:")
+ strlen (PATH_SENDMAIL) + 1);
sprintf (mailer_name, "sendmail:%s", PATH_SENDMAIL);
- mailvar_set ("sendmail", mailer_name, mailvar_type_string, MOPTF_OVERWRITE);
+ mailvar_set ("sendmail", mailer_name, mailvar_type_string,
+ MOPTF_OVERWRITE);
}
-
- args.args = NULL;
+ args.argc = 0;
+ args.argv = NULL;
args.file = NULL;
args.user = NULL;
- args.send_mode = 0;
+ args.hint = 0;
/* argument parsing */
#ifdef WITH_TLS
@@ -369,7 +399,14 @@ main (int argc, char **argv)
util_run_cached_commands (&command_list);
- if (!interactive)
+ if (interactive)
+ {
+ mu_debug_t debug;
+
+ mu_diag_get_debug (&debug);
+ mu_debug_set_print (debug, mail_diag_stderr_printer, NULL);
+ }
+ else
{
util_do_command ("set nocrt");
util_do_command ("set noasksub");
@@ -384,60 +421,33 @@ main (int argc, char **argv)
/* Interactive mode */
ml_readline_init ();
- mail_set_my_name(args.user);
+ mail_set_my_name (args.user);
/* Mode is just sending */
if (strcmp (mode, "send") == 0)
{
/* FIXME: set cmd to "mail [add1...]" */
char *buf = NULL;
- int num = 0;
int rc;
- if (args.args != NULL)
- while (args.args[num] != NULL)
- num++;
- mu_argcv_string (num, args.args, &buf);
+
+ mu_argcv_string (args.argc, args.argv, &buf);
rc = util_do_command ("mail %s", buf);
return mailvar_get (NULL, "mailx", mailvar_type_boolean, 0) ? rc : 0;
}
/* Or acting as a normal reader */
else
{
- /* open the mailbox */
- if (args.file == NULL)
+ if ((rc = mu_mailbox_create_default (&mbox, args.file)) != 0)
{
- if (args.user)
- {
- char *p = xmalloc (strlen (args.user) + 2);
- p[0] = '%';
- strcpy (p + 1, args.user);
- rc = mu_mailbox_create_default (&mbox, p);
- free (p);
- }
+ if (args.file)
+ util_error (_("Cannot create mailbox %s: %s"), args.file,
+ mu_strerror (rc));
else
- rc = mu_mailbox_create_default (&mbox, NULL);
- if (rc != 0)
- {
- util_error (_("Cannot create mailbox for %s: %s"), args.user,
- mu_strerror (rc));
- exit (EXIT_FAILURE);
- }
- }
- else if ((rc = mu_mailbox_create_default (&mbox, args.file)) != 0)
- {
- util_error (_("Cannot create mailbox %s: %s"), args.file,
- mu_strerror (rc));
+ util_error (_("Cannot create mailbox: %s"),
+ mu_strerror (rc));
exit (EXIT_FAILURE);
}
- /* Could we enable this at runtime, via the a set environment? */
- if (0)
- {
- mu_debug_t debug = NULL;
- mu_mailbox_get_debug (mbox, &debug);
- mu_debug_set_level (debug, MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT));
- }
-
if ((rc = mu_mailbox_open (mbox, MU_STREAM_RDWR|MU_STREAM_CREAT)) != 0)
{
mu_url_t url = NULL;
@@ -547,7 +557,7 @@ mail_warranty (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
fputs (_("GNU Mailutils -- a suite of utilities for electronic mail\n"
"Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,\n"
- "2007 Free Software Foundation, Inc.\n\n"),
+ "2007, 2009 Free Software Foundation, Inc.\n\n"),
ofile);
fputs (
_(" GNU Mailutils is free software; you can redistribute it and/or modify\n"

Return to:

Send suggestions and report system problems to the System administrator.