Commit 61295ae0 61295ae0e724c62ac016dfc374d6064c63270288 by Sergey Poznyakoff

Improve internal variable handling in mail. Implement envelope and variable commands.

* NEWS: Update.
* doc/texinfo/programs.texi: Document new variables and commands.
* mail/envelope.c: New file.
* mail/mailvar.c: New file.
* mail/Makefile.am (mail_SOURCES): Add envelope.c and mailvar.c.

* mail/mail.h (EF_HIDDEN): New constant
(mail_env_data_t, mail_env_entry, mail_env_entry_is_set)
(mail_env_entry, util_getenv, util_printenv, util_setenv)
(var_iterator_t, var_iterate_next, var_iterate_first)
(var_iterate_end, var_compl): Removed.

(union mailvar_value, struct mailvar_variable
(mail_variable, mail_envelope, print_envelope)
(mailvar_find_variable, mailvar_get, mailvar_print)
(mailvar_variable_format, mailvar_set, mailvar_set_compl): Add prototypes.
(MOPTF_OVERWRITE, MOPTF_QUIET)

* mail/table.c: List new commands: envelope, setq, variable.
Implement completion for `set'.
* mail/testsuite/mail/if.exp: Use setq to set a read-only variable.

mail/alias.c, mail/decode.c, mail/delete.c, mail/escape.c
mail/file.c, mail/folders.c, mail/from.c, mail/if.c,
mail/mail.c, mail/mailline.c, mail/msgset.y, mail/pipe.c,
mail/print.c, mail/quit.c, mail/reply.c, mail/send.c,
mail/set.c, mail/shell.c, mail/top.c, mail/unset.c,
mail/util.c: Use mailvar functions.
1 parent f6b40b8d
GNU mailutils NEWS -- history of user-visible changes. 2009-07-08
GNU mailutils NEWS -- history of user-visible changes. 2009-07-11
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -27,6 +27,44 @@ exists in the destination mailbox.
The `--verbose' command line option enables outputting additional
information.
* Mail
** envelope command
The env[elope] command displays the SMTP envelopes of the messages
given as its arguments.
** variable command
The va[riable] command describes the known internal mail variables.
When used with arguments, only variables named in the command line are
described.
For each variable, this command prints its name, data type, current
value and a short description.
** showenvelope variable
If the `showenvelope' variable is set, print command will include the
SMTP envelope in its output.
** fromfield variable
The `fromenvelope' boolean variable, if set, instructs mail to obtain
the sender address from the `From:' header. This is the default.
If unset, the sender address is obtained from the SMTP envelope.
** variable-strict variable
Setting this variable enables strict control over variable
settings. In this mode, mail prints warning if a user is trying to
set an unknown variable and refuses to set read-only variables.
** variable-pretty-print variable
If this variable is set, the `set' listing prints short
descriptions before each variable.
* API
* Wicket/Ticket functions
......
......@@ -3282,11 +3282,12 @@ The @samp{echo} (@samp{ec}) command prints its arguments to stdout.
The command @samp{source @var{filename}} reads commands from the named
file. Its minimal abbreviation is @samp{so}.
@anchor{Setting and Unsetting the Variables}
@subsubheading Setting and Unsetting the Variables
@kyindex set, mail command
@kyindex unset, mail command
The mail variables may be set using @samp{set} (@samp{se}) command. The
The mail variables are set using @samp{set} (@samp{se}) command. The
command takes a list of assignments. The syntax of an assignment is
@table @samp
......@@ -3322,6 +3323,58 @@ To undo the effect of the previous example, do:
& unset askcc crt indentprefix
@end smallexample
When used without arguments, both @command{set} or @command{unset}
list all currently defined variables. The form of this listing is
controlled by @code{variable-pretty-print} (@code{varpp}) variable. If
it is set, a description precedes each variable, e.g.:
@smallexample
# prompt user for subject before composing the message
ask
# prompt user for cc before composing the message
askcc
# output character set for decoded header fields
charset="auto"
# number of columns on terminal screen
columns=80
@end smallexample
If @code{variable-pretty-print} is not set, only the settings are
shown, e.g.:
@smallexample
ask
askcc
charset="auto"
columns=80
@end smallexample
@kyindex variable, mail command
A special command is provided to list all internal @command{mail}
variables:
@smallexample
variable [@var{names...}]
@end smallexample
If used without arguments, it prints all known internal variables. If
arguments are given, it displays only those internal variables that
are listed in command line. For each variable, this command prints its
name, data type, current value and a short description. For example:
@smallexample
& variable ask datefield
ask, asksub
Type: boolean
Current value: yes
prompt user for subject before composing the message
datefield
Type: boolean
Current value: [not set]
get date from the `Date:' header, instead of the envelope
@end smallexample
@subsubheading Setting and Unsetting Shell Environment Variables
Shell environment may be modified using @samp{setenv} (@samp{sete})
......@@ -3391,6 +3444,15 @@ set
Following variables control the behavior of GNU @command{mail}:
@table @code
@item append
@*Type: Boolean, Read-Only
@*Default: True
@vrindex append, mail variable
Messages saved in mbox are appended to the end rather than prepended.
This is the default and cannot be changed. This variable exists only
for compatibility with other @command{mailx} implementations.
@item appenddeadletter
@*Type: Boolean.
@*Default: False.
......@@ -3447,16 +3509,19 @@ message, the next one will be typed automatically.
When set, every occurrence of @code{!} in arguments to @code{!}
command is replaced with the last executed command.
@anchor{datefield}
@item datefield
@*Type: Boolean.
@*Default: False.
@vrindex datefield, mail variable
By default the date in a header summary is taken from the SMTP
By default the date in a header summary is taken from the @acronym{SMTP}
envelope of the message. Setting this variable tells @command{mail}
to use the date from @code{Date:} header field, converted to
local time. Notice, that for messages lacking this field @command{mail}
will fall back to using SMTP envelope.
will fall back to using @acronym{SMTP} envelope.
@xref{fromfield}.
@item charset
@*Type: string
......@@ -3520,6 +3585,14 @@ Unprintable characters are represented by their octal codes. Printable
ones are printed @samp{as is}.
@end table
@item debug
@*Type: Boolean
@*Default: Unset
@vrindex debug, mail variable
This variable is not used. It exists for compatibility with other
@command{mailx} implementations and for future use.
@item dot
@*Type: Boolean.
@*Default: False.
......@@ -3559,7 +3632,7 @@ denoting escapes.
@*Default: Unset
@vrindex flipr, mail variable
The variable @code{flipr} if set swaps the meanings of @code{reply}
If set, the variable @code{flipr} swaps the meanings of @code{reply}
and @code{Reply} commands (@pxref{Replying}).
@item folder
......@@ -3570,6 +3643,17 @@ and @code{Reply} commands (@pxref{Replying}).
The name of the directory to use for storing folders of messages. If
unset, @env{$HOME} is assumed.
@anchor{fromfield}
@item fromfield
@*Type: Boolean.
@*Default: True.
By default the sender address is taken from the @samp{From} header.
Unsetting this variable tells @command{mail} to obtain it from the
@acronym{SMTP} envelope, instead.
@xref{datefield}.
@item header
@*Type: Boolean.
@*Default: True, unless started with @option{--nosum} (@option{-N}) option.
......@@ -3621,6 +3705,15 @@ before entering send mode (@pxref{Composing Mail}). By default, the
address header fields are left intact while composing, the alias
expansion takes place immediately before sending message.
@item keep
@*Type: Boolean, Read-Only
@*Default: True
@vrindex append, mail variable
Truncate the user's system mailbox when it is empty, instead of
removing it. This is the default and cannot be changed. This variable
exists only for compatibility with other @command{mailx} implementations.
@item keepsave
@*Type: Boolean.
@*Default: False.
......@@ -3702,11 +3795,33 @@ is removed from the expansion. Setting this option causes the sender to
be included in the group.
@item mode
@*Type: String.
@*Type: String, Read-Only
@*Default: The name of current operation mode.
@vrindex mode, mail variable
Setting this variable does not affect the operation mode of the program.
This variable keeps the name of the current operation mode. Its
possible values are:
@table @asis
@item headers
The program is started with the @option{--headers} (@option{-H}) command
line option (@pxref{Invoking Mail}).
@item exist
The program is started with the @option{--exist} (@option{-e}) command
line option (@pxref{Invoking Mail}).
@item print
The program is started with the @option{--print} (@option{-p}) command
line option (@pxref{Invoking Mail}).
@item read
The progran operates in read mode. This is the default.
@item send
The program operates in send mode. This means it was given one or more
recipient addresses in the command line.
@end table
@item nullbody
@* Type: Boolean
......@@ -3732,6 +3847,13 @@ outputs something on its standard output or error:
@end group
@end smallexample
@item showenvelope
@*Type: Boolean
@*Default: Unset
If this variable is set, the @code{print} command will include the
@acronym{STMP} envelope in its output.
@item nullbodymsg
@*Type: String
@*Default: Null message body; hope that's ok
......@@ -3743,6 +3865,14 @@ this text, in accordance with the current locale, is displayed.
Unsetting this variable disables the warning.
@item onehop
@*Type: Boolean
@*Default: Unset
@vrindex onehop, mail variable
This variable is not used. It exists for compatibility with other
@command{mailx} implementations and for future use.
@item outfolder
@*Type: String.
@*Default: Unset.
......@@ -3767,6 +3897,14 @@ character after printing each message.
Contains the command prompt sequence.
@item quiet
@*Type: Boolean
@*Default: Unset
@vrindex quiet, mail variable
This variable is not used. It exists for compatibility with other
@command{mailx} implementations and for future use.
@item quit
@*Type: Boolean.
@*Default: False, unless started with @option{--quit} (@option{-q}) option.
......@@ -3782,6 +3920,16 @@ When set, causes keyboard interrupts to terminate the program.
When this variable is set, @command{mail} will read the system-wide
configuration file upon startup. See @ref{Mail Configuration Files}.
@item readonly
@*Type: Boolean
@*Default: False
@vrindex readonly, mail variable
When set, mailboxes are opened in readonly mode. In this mode, any
@command{mail} commands that alter the contents of the mailbox are
disabled. These commands include, but are not limited to:
@code{delete}, @code{save} and @code{mbox}.
@item record
@*Type: String.
@*Default: Unset.
......@@ -3853,7 +4001,23 @@ This variable contains the number of lines on terminal screen.
@*Default: sendmail:/usr/lib/sendmail
@vrindex sendmail, mail variable
Contains the URL of mail transport agent.
Contains URL of the mail transport agent.
@item sendwait
@*Type: Boolean
@*Default: Unset
@vrindex sendwait, mail variable
This variable is not used. It exists for compatibility with other
@command{mailx} implementations and for future use.
@item showto
@*Type: Boolean
@*Default: False
@vrindex showto, mail variable
If the message was sent by the user, print its recipient address in
the header summary.
@item Sign
@*Type: String.
......@@ -3897,6 +4061,26 @@ off.
Number of lines to be displayed by @code{top} and @code{Top} commands.
@item variable-strict
@itemx varstrict
@*Type: Boolean.
@*Default: False.
Setting this variable enables strict control over variable
settings. In this mode, @command{mail} refuses to set read-only
variables. Also, if the user is trying to set an unknown variable,
@command{mail} prints a warning.
@xref{Setting and Unsetting the Variables}.
@item variable-pretty-print
@itemx varpp
@*Type: Boolean.
@*Default: False.
If this variable is set, the listing ouput by @command{set} contains short
descriptions before each variable. @xref{Setting and Unsetting the Variables}.
@item verbose
@*Type: Boolean.
@*Default: False.
......
......@@ -49,6 +49,7 @@ mail_SOURCES = \
dp.c\
echo.c\
edit.c\
envelope.c\
eq.c\
escape.c\
exit.c\
......@@ -65,6 +66,7 @@ mail_SOURCES = \
mail.c\
mail.h\
mailline.c\
mailvar.c\
mbox.c\
msgset.y\
next.c\
......
......@@ -152,7 +152,7 @@ alias_expand (const char *name)
alias_t al;
mu_list_t list;
if (util_getenv (NULL, "recursivealiases", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "recursivealiases", mailvar_type_boolean, 0) == 0)
{
char *s;
mu_list_t origlist;
......
......@@ -182,7 +182,7 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset,
if (mu_message_unencapsulate (mesg, &submsg, NULL) == 0)
display_message0 (submsg, msgset, select_hdr);
}
else if (util_getenv (&tmp, "metamail", Mail_env_string, 0) == 0)
else if (mailvar_get (&tmp, "metamail", mailvar_type_string, 0) == 0)
{
/* If `metamail' is set to a string, treat it as command line
of external metamail program. */
......@@ -212,13 +212,13 @@ display_message0 (mu_message_t mesg, const msgset_t *msgset,
/* If `metamail' is set to true, enable internal mailcap
support */
if (util_getenv (NULL, "metamail", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "metamail", mailvar_type_boolean, 0) == 0)
{
char *no_ask = NULL;
int debug = 0;
util_getenv (&no_ask, "mimenoask", Mail_env_string, 0);
if (util_getenv (&debug, "verbose", Mail_env_boolean, 0) == 0
mailvar_get (&no_ask, "mimenoask", mailvar_type_string, 0);
if (mailvar_get (&debug, "verbose", mailvar_type_boolean, 0) == 0
&& debug)
debug = 9;
......@@ -347,7 +347,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg)
char *no_ask;
setenv ("METAMAIL_PAGER", getenv ("PAGER"), 0);
if (util_getenv (&no_ask, "mimenoask", Mail_env_string, 0))
if (mailvar_get (&no_ask, "mimenoask", mailvar_type_string, 0))
setenv ("MM_NOASK", no_ask, 1);
status = mu_message_get_stream (mesg, &stream);
......
......@@ -40,7 +40,7 @@ mail_delete (int argc, char **argv)
int rc = util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT,
mail_delete_msg, NULL);
if (util_getenv (NULL, "autoprint", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "autoprint", mailvar_type_boolean, 0) == 0)
util_do_command("print");
return rc;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2009 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 "mail.h"
/*
* env[elope] [msglist]
*/
int
print_envelope (msgset_t *mspec, mu_message_t msg, void *data)
{
int status;
mu_envelope_t env = NULL;
const char *sender = NULL, *date = NULL;
status = mu_message_get_envelope (msg, &env);
if (status)
{
mu_error (_("%d: Cannot get envelope"), mspec->msg_part[0]);
}
else
{
mu_envelope_sget_sender (env, &sender);
mu_envelope_sget_date (env, &date);
if (data)
fprintf (ofile, "%s ", (char*) data);
fprintf (ofile, "%s %s", sender, date);
}
return 0;
}
int
mail_envelope (int argc, char **argv)
{
return util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT,
print_envelope, NULL);
}
......@@ -164,7 +164,7 @@ escape_check_args (int argc, char **argv)
if (argc == 1)
{
char *escape = "~";
util_getenv (&escape, "escape", Mail_env_string, 0);
mailvar_get (&escape, "escape", mailvar_type_string, 0);
util_error (_("%c%s requires an argument"), escape[0], argv[0]);
return 1;
}
......@@ -234,8 +234,8 @@ escape_sign (int argc MU_ARG_UNUSED, char **argv, compose_env_t *env MU_ARG_UNUS
{
char *p;
if (util_getenv (&p, mu_isupper (argv[0][0]) ? "Sign" : "sign",
Mail_env_string, 1) == 0)
if (mailvar_get (&p, mu_isupper (argv[0][0]) ? "Sign" : "sign",
mailvar_type_string, 1) == 0)
{
fputs ("-- \n", ofile);
if (mu_isupper (argv[0][0]))
......@@ -315,7 +315,7 @@ run_editor (char *ed, char *arg)
static int
escape_run_editor (char *ed, int argc, char **argv, compose_env_t *env)
{
if (!util_getenv (NULL, "editheaders", Mail_env_boolean, 0))
if (!mailvar_get (NULL, "editheaders", mailvar_type_boolean, 0))
{
char *filename;
int fd = mu_tempfile (NULL, &filename);
......@@ -413,29 +413,9 @@ escape_headers (int argc, char **argv, compose_env_t *env)
int
escape_insert (int argc, char **argv, compose_env_t *send_env MU_ARG_UNUSED)
{
struct mail_env_entry *env;
if (escape_check_args (argc, argv))
return 1;
env = util_find_env (argv[1], 0);
if (env)
switch (env->type)
{
case Mail_env_string:
fprintf (ofile, "%s", env->value.string);
break;
case Mail_env_number:
fprintf (ofile, "%d", env->value.number);
break;
case Mail_env_boolean:
fprintf (ofile, "%s", env->set ? "yes" : "no");
break;
default:
break;
}
mailvar_variable_format (ofile, mailvar_find_variable (argv[1], 0), NULL);
return 0;
}
......@@ -455,7 +435,7 @@ quote0 (msgset_t *mspec, mu_message_t mesg, void *data)
fprintf (stdout, _("Interpolating: %d\n"), mspec->msg_part[0]);
util_getenv (&prefix, "indentprefix", Mail_env_string, 0);
mailvar_get (&prefix, "indentprefix", mailvar_type_string, 0);
if (*(int*)data)
{
......
......@@ -118,7 +118,7 @@ mail_file (int argc, char **argv)
mbox = newbox;
mu_mailbox_messages_count (mbox, &total);
set_cursor (1);
if (util_getenv (NULL, "header", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "header", mailvar_type_boolean, 0) == 0)
{
util_do_command ("summary");
util_do_command ("z.");
......
......@@ -27,7 +27,7 @@ mail_folders (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
char *path;
if (util_getenv (&path, "folder", Mail_env_string, 1))
if (mailvar_get (&path, "folder", mailvar_type_string, 1))
return 1;
if (path[0] != '/' && path[0] != '~')
......
......@@ -36,48 +36,60 @@ mail_from0 (msgset_t *mspec, mu_message_t msg, void *data)
int cflag;
size_t m_size = 0, m_lines = 0;
mu_message_get_header (msg, &hdr);
if (mu_header_aget_value_unfold (hdr, MU_HEADER_FROM, &from) == 0)
{
mu_address_t address = NULL;
if (mu_address_create (&address, from) == 0)
if (mailvar_get (NULL, "fromfield", mailvar_type_boolean, 0) == 0)
{
mu_message_get_header (msg, &hdr);
if (mu_header_aget_value_unfold (hdr, MU_HEADER_FROM, &from) == 0)
{
char *name;
const char *email;
if (mu_address_sget_email (address, 1, &email) == 0)
mu_address_t address = NULL;
if (mu_address_create (&address, from) == 0)
{
if (util_getenv (NULL, "showto", Mail_env_boolean, 0) == 0
&& mail_is_my_name (email))
char *name;
const char *email;
if (mu_address_sget_email (address, 1, &email) == 0)
{
char *tmp;
if (mu_header_aget_value_unfold (hdr, MU_HEADER_TO,
&tmp) == 0)
if (mailvar_get (NULL, "showto", mailvar_type_boolean, 0) == 0
&& mail_is_my_name (email))
{
mu_address_t addr_to;
if (mu_address_create (&addr_to, tmp) == 0)
char *tmp;
if (mu_header_aget_value_unfold (hdr, MU_HEADER_TO,
&tmp) == 0)
{
mu_address_destroy (&address);
address = addr_to;
mu_address_t addr_to;
if (mu_address_create (&addr_to, tmp) == 0)
{
mu_address_destroy (&address);
address = addr_to;
}
free (tmp);
}
free (tmp);
}
}
}
if ((mu_address_aget_personal (address, 1, &name) == 0
&& name)
|| (mu_address_aget_email (address, 1, &name) == 0
&& name))
{
free (from);
from = name;
if ((mu_address_aget_personal (address, 1, &name) == 0
&& name)
|| (mu_address_aget_email (address, 1, &name) == 0
&& name))
{
free (from);
from = name;
}
mu_address_destroy (&address);
}
mu_address_destroy (&address);
}
util_rfc2047_decode (&from);
}
else
{
mu_envelope_t env = NULL;
const char *sender = "";
if (mu_message_get_envelope (msg, &env) == 0)
mu_envelope_sget_sender (env, &sender);
from = strdup (sender);
}
util_rfc2047_decode (&from);
mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT, &subj);
util_rfc2047_decode (&subj);
......@@ -100,7 +112,7 @@ mail_from0 (msgset_t *mspec, mu_message_t msg, void *data)
cflag = ' ';
date[0] = 0;
if (util_getenv (NULL, "datefield", Mail_env_boolean, 0) == 0
if (mailvar_get (NULL, "datefield", mailvar_type_boolean, 0) == 0
&& mu_header_get_value (hdr, MU_HEADER_DATE, date, sizeof (date), NULL) == 0)
{
time_t t;
......
......@@ -97,7 +97,7 @@ mail_if (int argc, char **argv)
return 1;
}
if (util_getenv (&mode, "mode", Mail_env_string, 1))
if (mailvar_get (&mode, "mode", mailvar_type_string, 1))
exit (EXIT_FAILURE);
if (if_cond() == 0)
......
......@@ -77,7 +77,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case 'e':
util_cache_command (&command_list, "set mode=exist");
util_cache_command (&command_list, "setq mode=exist");
break;
case 'f':
......@@ -102,7 +102,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'p':
case 'r':
util_cache_command (&command_list, "set mode=print");
util_cache_command (&command_list, "setq mode=print");
break;
case 'q':
......@@ -110,11 +110,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case 't':
util_cache_command (&command_list, "set mode=send");
util_cache_command (&command_list, "setq mode=send");
break;
case 'H':
util_cache_command (&command_list, "set mode=headers");
util_cache_command (&command_list, "setq mode=headers");
break;
case 'i':
......@@ -144,7 +144,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case 'F':
util_cache_command (&command_list, "set byname");
/* FIXME */
util_cache_command (&command_list, "setq byname");
break;
case ARGP_KEY_ARG:
......@@ -157,7 +158,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case ARGP_KEY_FINI:
if (args->send_mode)
util_cache_command (&command_list, "set mode=send");
util_cache_command (&command_list, "setq mode=send");
break;
default:
......@@ -192,7 +193,7 @@ mail_cmdline (void *closure, int cont MU_ARG_UNUSED)
while (1)
{
if (util_getenv (NULL, "autoinc", Mail_env_boolean, 0) == 0
if (mailvar_get (NULL, "autoinc", mailvar_type_boolean, 0) == 0
&& !mu_mailbox_is_updated (mbox))
{
mu_mailbox_messages_count (mbox, &total);
......@@ -208,7 +209,7 @@ mail_cmdline (void *closure, int cont MU_ARG_UNUSED)
continue;
}
if (!rc && util_getenv (NULL, "ignoreeof", Mail_env_boolean, 0) == 0)
if (!rc && mailvar_get (NULL, "ignoreeof", mailvar_type_boolean, 0) == 0)
{
util_error (_("Use \"quit\" to quit."));
continue;
......@@ -220,8 +221,8 @@ mail_cmdline (void *closure, int cont MU_ARG_UNUSED)
}
static char *default_setup[] = {
"set noallnet",
"set noappend",
/* "set noallnet", */
"setq append",
"set asksub",
"set crt",
"set noaskbcc",
......@@ -239,7 +240,7 @@ static char *default_setup[] = {
"set noignore",
"set noignoreeof",
"set indentprefix=\"\t\"",
"set nokeep",
"setq keep",
"set nokeepsave",
"set nometoo",
"set noonehop",
......@@ -265,9 +266,10 @@ static char *default_setup[] = {
"set metamail",
"set recursivealiases",
"set noinplacealiases",
"set fromfield",
/* Start in mail reading mode */
"set mode=read",
"setq mode=read",
"set noquit",
"set rc",
......@@ -343,7 +345,7 @@ main (int argc, char **argv)
char *mailer_name = alloca (strlen ("sendmail:")
+ strlen (PATH_SENDMAIL) + 1);
sprintf (mailer_name, "sendmail:%s", PATH_SENDMAIL);
util_setenv ("sendmail", mailer_name, Mail_env_string, 1);
mailvar_set ("sendmail", mailer_name, mailvar_type_string, MOPTF_OVERWRITE);
}
......@@ -361,7 +363,7 @@ main (int argc, char **argv)
exit (1);
/* read system-wide mail.rc and user's .mailrc */
if (util_getenv (NULL, "rc", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "rc", mailvar_type_boolean, 0) == 0)
util_do_command ("source %s", SITE_MAIL_RC);
util_do_command ("source %s", getenv ("MAILRC"));
......@@ -376,7 +378,7 @@ main (int argc, char **argv)
}
/* how should we be running? */
if (util_getenv (&mode, "mode", Mail_env_string, 1))
if (mailvar_get (&mode, "mode", mailvar_type_string, 1))
exit (EXIT_FAILURE);
/* Interactive mode */
......@@ -396,7 +398,7 @@ main (int argc, char **argv)
num++;
mu_argcv_string (num, args.args, &buf);
rc = util_do_command ("mail %s", buf);
return util_getenv (NULL, "mailx", Mail_env_boolean, 0) ? rc : 0;
return mailvar_get (NULL, "mailx", mailvar_type_boolean, 0) ? rc : 0;
}
/* Or acting as a normal reader */
else
......@@ -474,7 +476,7 @@ main (int argc, char **argv)
if (total == 0
&& (strcmp (mode, "read")
|| util_getenv (NULL, "emptystart", Mail_env_boolean, 0)))
|| mailvar_get (NULL, "emptystart", mailvar_type_boolean, 0)))
{
if (args.file)
fprintf (ofile, _("%s: 0 messages\n"), args.file);
......@@ -485,13 +487,13 @@ main (int argc, char **argv)
}
/* initial commands */
if (util_getenv (NULL, "header", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "header", mailvar_type_boolean, 0) == 0)
{
util_do_command ("summary");
util_do_command ("z.");
}
util_getenv (&prompt, "prompt", Mail_env_string, 0);
mailvar_get (&prompt, "prompt", mailvar_type_string, 0);
mail_mainloop (mail_cmdline, (void*) prompt, 1);
fprintf (ofile, "\n");
util_do_command ("quit");
......
......@@ -98,10 +98,11 @@ typedef int function_t (int, char **);
#endif
/* Values for mail_command_entry.flags */
#define EF_REG 0x00 /* Regular command */
#define EF_FLOW 0x01 /* Flow control command */
#define EF_SEND 0x02 /* Send command */
#define EF_REG 0x00 /* Regular command */
#define EF_FLOW 0x01 /* Flow control command */
#define EF_SEND 0x02 /* Send command */
#define EF_HIDDEN 0x04 /* Hiddent command */
typedef struct compose_env
{
mu_header_t header; /* The message headers */
......@@ -139,31 +140,29 @@ struct mail_escape_entry
int (*escfunc) (int, char **, compose_env_t *);
};
typedef enum
enum mailvar_type
{
Mail_env_whatever,
Mail_env_number,
Mail_env_string,
Mail_env_boolean
}
mail_env_data_t;
struct mail_env_entry
mailvar_type_whatever,
mailvar_type_number,
mailvar_type_string,
mailvar_type_boolean
};
union mailvar_value
{
char *string;
int number;
int bool;
};
struct mailvar_variable
{
const char *var;
mail_env_data_t type;
char *name;
enum mailvar_type type;
int set;
union
{
char *string;
int number;
int bool;
}
value;
union mailvar_value value;
};
#define mail_env_entry_is_set(ep) ((ep) && (ep)->set)
typedef struct message_set msgset_t;
struct message_set
......@@ -212,6 +211,7 @@ extern int mail_send (int argc, char **argv); /* command mail */
extern int mail_mbox (int argc, char **argv);
extern int mail_next (int argc, char **argv);
extern int mail_nounfold (int argc, char **argv);
extern int mail_variable (int argc, char **argv);
extern int mail_pipe (int argc, char **argv);
extern int mail_previous (int argc, char **argv);
extern int mail_print (int argc, char **argv);
......@@ -240,6 +240,8 @@ extern int mail_write (int argc, char **argv);
extern int mail_z (int argc, char **argv);
extern int mail_eq (int argc, char **argv); /* command = */
extern int mail_setenv (int argc, char **argv);
extern int mail_envelope (int argc, char **argv);
extern int print_envelope (msgset_t *mspec, mu_message_t msg, void *data);
extern int if_cond (void);
......@@ -331,13 +333,19 @@ extern int util_getlines (void);
extern int util_screen_lines (void);
extern int util_screen_columns (void);
extern int util_get_crt (void);
extern struct mail_env_entry *util_find_env (const char *var, int create);
extern int util_getenv (void *ptr, const char *variable,
mail_env_data_t type, int warn);
extern void util_printenv (int set);
extern int util_setenv (const char *name, void *value,
mail_env_data_t type, int overwrite);
extern struct mailvar_variable *mailvar_find_variable (const char *var, int create);
extern int mailvar_get (void *ptr, const char *variable,
enum mailvar_type type, int warn);
extern void mailvar_print (int set);
extern void mailvar_variable_format (FILE *fp,
const struct mailvar_variable *,
const char *defval);
#define MOPTF_OVERWRITE 0x001
#define MOPTF_QUIET 0x002
extern int mailvar_set (const char *name, void *value,
enum mailvar_type type, int flags);
extern int util_isdeleted (size_t msgno);
extern char *util_get_homedir (void);
extern char *util_fullpath (const char *inpath);
......@@ -396,11 +404,6 @@ extern int mail_sender (int argc, char **argv);
extern int mail_nosender (int argc, char **argv);
extern mu_address_t get_sender_address (mu_message_t msg);
typedef struct var_iterator *var_iterator_t;
extern const char *var_iterate_next (var_iterator_t itr);
extern const char *var_iterate_first (const char *prefix, var_iterator_t *pitr);
extern void var_iterate_end (var_iterator_t *itr);
#define COMPOSE_APPEND 0
#define COMPOSE_REPLACE 1
#define COMPOSE_SINGLE_LINE 2
......@@ -427,6 +430,8 @@ extern char *readline (char *prompt);
#define MAIL_ATTRIBUTE_TAGGED 0x0004
#define MAIL_ATTRIBUTE_SHOWN 0x0008
extern void ml_attempted_completion_over (void);
#ifdef WITH_READLINE
extern char **file_compl (int argc, char **argv, int ws);
extern char **no_compl (int argc, char **argv, int ws);
......@@ -435,7 +440,7 @@ extern char **msglist_file_compl (int argc, char **argv, int ws);
extern char **dir_compl (int argc, char **argv, int ws);
extern char **command_compl (int argc, char **argv, int ws);
extern char **alias_compl (int argc, char **argv, int ws);
extern char **var_compl (int argc, char **argv, int ws);
extern char **mailvar_set_compl (int argc, char **argv, int ws);
extern char **exec_compl (int argc, char **argv, int ws);
#else
# define file_compl NULL
......
......@@ -35,7 +35,7 @@ sig_handler (int signo)
switch (signo)
{
case SIGINT:
if (util_getenv (NULL, "quit", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "quit", mailvar_type_boolean, 0) == 0)
exit (0);
_interrupted++;
break;
......@@ -564,32 +564,6 @@ alias_compl (int argc, char **argv, int ws)
}
static char *
var_generator (const char *text, int state)
{
static var_iterator_t itr;
const char *p;
if (!state)
p = var_iterate_first (text, &itr);
else
p = var_iterate_next (itr);
if (!p)
{
var_iterate_end (&itr);
return NULL;
}
return strdup (p);
}
char **
var_compl (int argc, char **argv, int ws)
{
ml_attempted_completion_over ();
return rl_completion_matches (ws ? "" : argv[argc-1], var_generator);
}
static char *
mkfilename (const char *dir, const char *file)
{
size_t len = strlen (dir) + 1 + strlen (file) + 1;
......
......@@ -574,7 +574,7 @@ select_header (mu_message_t msg, void *closure)
mu_message_get_header (msg, &hdr);
if (mu_header_aget_value (hdr, header, &contents) == 0)
{
if (util_getenv (NULL, "regex", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "regex", mailvar_type_boolean, 0) == 0)
{
/* Match string against the extended regular expression(ignoring
case) in pattern, treating errors as no match.
......@@ -612,7 +612,7 @@ int
select_body (mu_message_t msg, void *closure)
{
char *expr = closure;
int noregex = util_getenv (NULL, "regex", Mail_env_boolean, 0);
int noregex = mailvar_get (NULL, "regex", mailvar_type_boolean, 0);
regex_t re;
int status;
mu_body_t body = NULL;
......
......@@ -37,7 +37,7 @@ mail_pipe (int argc, char **argv)
if (argc > 2)
cmd = argv[--argc];
else if (util_getenv (&cmd, "cmd", Mail_env_string, 1))
else if (mailvar_get (&cmd, "cmd", mailvar_type_string, 1))
return 1;
if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT, &list))
......@@ -58,7 +58,7 @@ mail_pipe (int argc, char **argv)
fprintf (tube, "%s", buffer);
off += n;
}
if (util_getenv (NULL, "page", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "page", mailvar_type_boolean, 0) == 0)
fprintf (tube, "\f\n");
}
util_mark_read (msg);
......
......@@ -39,7 +39,9 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data)
int pagelines = util_get_crt ();
mu_message_lines (mesg, &lines);
if (mailvar_get (NULL, "showenvelope", mailvar_type_boolean, 0) == 0)
lines++;
/* If it is POP or IMAP the lines number is not known, so try
to be smart about it. */
if (lines == 0)
......@@ -59,6 +61,9 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data)
if (pagelines && lines > pagelines)
out = popen (getenv ("PAGER"), "w");
if (mailvar_get (NULL, "showenvelope", mailvar_type_boolean, 0) == 0)
print_envelope (mspec, mesg, "From");
if (*(int *) data) /* print was called with a lowercase 'p' */
{
size_t i, num = 0;
......
......@@ -41,7 +41,7 @@ mail_mbox_close ()
if (!mbox)
return 0;
if (util_getenv (NULL, "readonly", Mail_env_boolean, 0))
if (mailvar_get (NULL, "readonly", mailvar_type_boolean, 0))
{
if (mail_mbox_commit ())
return 1;
......@@ -69,8 +69,8 @@ mail_mbox_commit ()
int saved_count = 0;
mu_message_t msg;
mu_attribute_t attr;
int keepsave = util_getenv (NULL, "keepsave", Mail_env_boolean, 0) == 0;
int hold = util_getenv (NULL, "hold", Mail_env_boolean, 0) == 0;
int keepsave = mailvar_get (NULL, "keepsave", mailvar_type_boolean, 0) == 0;
int hold = mailvar_get (NULL, "hold", mailvar_type_boolean, 0) == 0;
mu_url_t url;
int is_user_mbox;
......
......@@ -85,7 +85,7 @@ reply0 (msgset_t *mspec, mu_message_t msg, void *data)
const char *email;
if (mu_address_sget_email (addr, i, &email) || email == NULL)
continue;
if ((util_getenv (NULL, "metoo", Mail_env_boolean, 0) == 0)
if ((mailvar_get (NULL, "metoo", mailvar_type_boolean, 0) == 0)
|| !mail_is_my_name (email))
compose_header_set (&env, MU_HEADER_TO,
email,
......@@ -133,7 +133,7 @@ int
mail_reply (int argc, char **argv)
{
int lower = mu_islower (argv[0][0]);
if (util_getenv (NULL, "flipr", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "flipr", mailvar_type_boolean, 0) == 0)
lower = !lower;
return util_foreach_msg (argc, argv, MSG_NODELETED, reply0, &lower);
}
......
......@@ -138,10 +138,10 @@ mail_sendheader (int argc, char **argv)
static void
read_cc_bcc (compose_env_t *env)
{
if (util_getenv (NULL, "askcc", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "askcc", mailvar_type_boolean, 0) == 0)
compose_header_set (env, MU_HEADER_CC,
ml_readline_with_intr ("Cc: "), COMPOSE_REPLACE);
if (util_getenv (NULL, "askbcc", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "askbcc", mailvar_type_boolean, 0) == 0)
compose_header_set (env, MU_HEADER_BCC,
ml_readline_with_intr ("Bcc: "), COMPOSE_REPLACE);
}
......@@ -193,10 +193,10 @@ mail_send (int argc, char **argv)
}
}
if (util_getenv (NULL, "mailx", Mail_env_boolean, 0))
if (mailvar_get (NULL, "mailx", mailvar_type_boolean, 0))
read_cc_bcc (&env);
if (util_getenv (NULL, "asksub", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "asksub", mailvar_type_boolean, 0) == 0)
compose_header_set (&env, MU_HEADER_SUBJECT,
ml_readline_with_intr ("Subject: "), COMPOSE_REPLACE);
......@@ -234,7 +234,7 @@ compose_header_set (compose_env_t * env, const char *name,
case COMPOSE_REPLACE:
case COMPOSE_APPEND:
if (is_address_field (name)
&& util_getenv (NULL, "inplacealiases", Mail_env_boolean, 0) == 0)
&& mailvar_get (NULL, "inplacealiases", mailvar_type_boolean, 0) == 0)
{
char *exp = alias_expand (value);
status = mu_header_set_value (env->header, name, exp ? exp : value,
......@@ -250,7 +250,7 @@ compose_header_set (compose_env_t * env, const char *name,
&& old_value[0])
{
if (is_address_field (name)
&& util_getenv (NULL, "inplacealiases", Mail_env_boolean, 0) == 0)
&& mailvar_get (NULL, "inplacealiases", mailvar_type_boolean, 0) == 0)
{
char *exp = alias_expand (value);
status = util_merge_addresses (&old_value, exp ? exp : value);
......@@ -322,10 +322,10 @@ fill_body (mu_message_t msg, FILE *file)
if (offset == 0)
{
if (util_getenv (NULL, "nullbody", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "nullbody", mailvar_type_boolean, 0) == 0)
{
char *str;
if (util_getenv (&str, "nullbodymsg", Mail_env_string, 0) == 0)
if (mailvar_get (&str, "nullbodymsg", mailvar_type_string, 0) == 0)
util_error ("%s\n", _(str));
}
else
......@@ -384,7 +384,7 @@ mail_send0 (compose_env_t * env, int save_to)
if (ml_got_interrupt ())
{
if (util_getenv (NULL, "ignore", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "ignore", mailvar_type_boolean, 0) == 0)
{
fprintf (stdout, "@\n");
}
......@@ -402,9 +402,9 @@ mail_send0 (compose_env_t * env, int save_to)
if (!buf)
{
if (interactive
&& util_getenv (NULL, "ignoreeof", Mail_env_boolean, 0) == 0)
&& mailvar_get (NULL, "ignoreeof", mailvar_type_boolean, 0) == 0)
{
util_error (util_getenv (NULL, "dot", Mail_env_boolean, 0) == 0 ?
util_error (mailvar_get (NULL, "dot", mailvar_type_boolean, 0) == 0 ?
_("Use \".\" to terminate letter.") :
_("Use \"~.\" to terminate letter."));
continue;
......@@ -416,9 +416,9 @@ mail_send0 (compose_env_t * env, int save_to)
int_cnt = 0;
if (strcmp (buf, ".") == 0
&& util_getenv (NULL, "dot", Mail_env_boolean, 0) == 0)
&& mailvar_get (NULL, "dot", mailvar_type_boolean, 0) == 0)
done = 1;
else if (util_getenv (&escape, "escape", Mail_env_string, 0) == 0
else if (mailvar_get (&escape, "escape", mailvar_type_string, 0) == 0
&& buf[0] == escape[0])
{
if (buf[1] == buf[0])
......@@ -471,11 +471,11 @@ mail_send0 (compose_env_t * env, int save_to)
/* If interrupted dump the file to dead.letter. */
if (int_cnt)
{
if (util_getenv (NULL, "save", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "save", mailvar_type_boolean, 0) == 0)
{
FILE *fp = fopen (getenv ("DEAD"),
util_getenv (NULL, "appenddeadletter",
Mail_env_boolean, 0) == 0 ?
mailvar_get (NULL, "appenddeadletter",
mailvar_type_boolean, 0) == 0 ?
"a" : "w");
if (!fp)
......@@ -505,11 +505,11 @@ mail_send0 (compose_env_t * env, int save_to)
/* In mailx compatibility mode, ask for Cc and Bcc after editing
the body of the message */
if (util_getenv (NULL, "mailx", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "mailx", mailvar_type_boolean, 0) == 0)
read_cc_bcc (env);
/* Prepare the header */
if (util_getenv (NULL, "xmailer", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "xmailer", mailvar_type_boolean, 0) == 0)
mu_header_set_value (env->header, MU_HEADER_X_MAILER,
program_version, 1);
......@@ -594,13 +594,13 @@ mail_send0 (compose_env_t * env, int save_to)
|| compose_header_get (env, MU_HEADER_BCC, NULL))
{
char *sendmail;
if (util_getenv (&sendmail, "sendmail", Mail_env_string, 0)
if (mailvar_get (&sendmail, "sendmail", mailvar_type_string, 0)
== 0)
{
int status = mu_mailer_create (&mailer, sendmail);
if (status == 0)
{
if (util_getenv (NULL, "verbose", Mail_env_boolean, 0)
if (mailvar_get (NULL, "verbose", mailvar_type_boolean, 0)
== 0)
{
mu_debug_t debug = NULL;
......
......@@ -29,9 +29,11 @@
int
mail_set (int argc, char **argv)
{
int flags = MOPTF_OVERWRITE | ((strcmp (argv[0], "setq") == 0) ? MOPTF_QUIET : 0);
if (argc < 2)
{
util_printenv (1);
mailvar_print (1);
return 0;
}
else
......@@ -46,7 +48,7 @@ mail_set (int argc, char **argv)
if (!strncmp ("no", argv[i], 2) && !value)
{
util_setenv (&argv[i][2], NULL, Mail_env_boolean, 1);
mailvar_set (&argv[i][2], NULL, mailvar_type_boolean, flags);
}
else if (value)
{
......@@ -55,14 +57,14 @@ mail_set (int argc, char **argv)
nval = strtoul (value, &p, 0);
if (*p == 0)
util_setenv (argv[i], &nval, Mail_env_number, 1);
mailvar_set (argv[i], &nval, mailvar_type_number, flags);
else
util_setenv (argv[i], value, Mail_env_string, 1);
mailvar_set (argv[i], value, mailvar_type_string, flags);
}
else
{
int dummy = 1;
util_setenv (argv[i], &dummy, Mail_env_boolean, 1);
mailvar_set (argv[i], &dummy, mailvar_type_boolean, flags);
}
}
return 0;
......
......@@ -25,7 +25,7 @@ expand_bang (char **pbuf)
char *tmp, *p, *q;
size_t count = 0;
util_getenv (&last, "gnu-last-command", Mail_env_string, 0);
mailvar_get (&last, "gnu-last-command", mailvar_type_string, 0);
for (p = *pbuf; *p; p++)
if (*p == '!')
......@@ -75,7 +75,7 @@ mail_execute (int shell, int argc, char **argv)
}
/* Expand arguments if required */
if (util_getenv (NULL, "bang", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "bang", mailvar_type_boolean, 0) == 0)
{
int i;
......@@ -85,7 +85,8 @@ mail_execute (int shell, int argc, char **argv)
/* Construct command line and save it to gnu-last-command variable */
mu_argcv_string (argc, argv, &buf);
util_setenv ("gnu-last-command", buf, Mail_env_string, 1);
mailvar_set ("gnu-last-command", buf, mailvar_type_string,
MOPTF_QUIET|MOPTF_OVERWRITE);
/* Do actual work */
......
......@@ -52,6 +52,8 @@ static const struct mail_command_entry mail_command_table[] = {
mail_else, no_compl },
{ "en", "endif", "en[dif]", EF_FLOW,
mail_endif, no_compl },
{ "env", "envelope", "en[velope]", 0,
mail_envelope, msglist_compl },
{ "ex", "exit", "ex[it]", 0,
mail_exit, no_compl },
{ "F", "Followup", "F[ollowup] [msglist]", EF_SEND,
......@@ -121,6 +123,8 @@ static const struct mail_command_entry mail_command_table[] = {
{ "sen", "sendheader", "sen[dheader] [[header][: value]]", EF_SEND,
mail_sendheader, no_compl },
{ "se", "set", "se[t] [name[=[string]]...] [name=number...] [noname...]", 0,
mail_set, mailvar_set_compl },
{ "setq", "setq", NULL, EF_HIDDEN,
mail_set, no_compl },
{ "sender", "sen", "sen[der] [header-field...]", 0,
mail_sender, no_compl },
......@@ -151,9 +155,11 @@ static const struct mail_command_entry mail_command_table[] = {
{ "unf", "unfold", "unf[old] [header-field]", 0,
mail_unfold, no_compl },
{ "uns", "unset", "uns[et] name...", 0,
mail_unset, var_compl },
mail_unset, mailvar_set_compl },
{ "unt", "untag", "unt[ag] [msglist]", 0,
mail_tag, msglist_compl },
{ "va", "variable", "variable [name...]", 0,
mail_variable, mailvar_set_compl },
{ "ve", "version", "ve[rsion]", 0,
mail_version, no_compl },
{ "v", "visual", "v[isual] [msglist]", 0,
......
# -*- tcl -*-
# This file is part of Mailutils testsuite.
# Copyright (C) 2002, 2005, 2007 Free Software Foundation
# Copyright (C) 2002, 2005, 2007, 2009 Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -43,7 +43,7 @@ mu_test_file "$MU_FOLDER_DIR/if.out" \
"Held 5 messages in $MU_SPOOL_DIR/mbox1"
mu_exec -message "Send mode on TTY" \
-arg "--exec='set mode=send'" \
-arg "--exec='setq mode=send'" \
-arg "--exec='source ${srcdir}/if.mail'" \
-arg "--exec=quit" \
"Begin test" \
......@@ -51,7 +51,7 @@ mu_exec -message "Send mode on TTY" \
"End test"
mu_exec -message "Send mode not on TTY" \
-arg "--exec='set mode=send'" \
-arg "--exec='setq mode=send'" \
-arg "--exec='source ${srcdir}/if.mail'" \
-arg "--exec=quit" \
-arg "> $MU_FOLDER_DIR/if.out"
......@@ -62,7 +62,7 @@ mu_test_file "$MU_FOLDER_DIR/if.out" \
"End test"
mu_exec -message "Nomode on TTY" \
-arg "--exec='set mode=nomode'" \
-arg "--exec='setq mode=nomode'" \
-arg "--exec='source ${srcdir}/if.mail'" \
-arg "--exec=quit" \
"Begin test" \
......@@ -70,7 +70,7 @@ mu_exec -message "Nomode on TTY" \
"End test"
mu_exec -message "Nomode not on TTY" \
-arg "--exec='set mode=nomode'" \
-arg "--exec='setq mode=nomode'" \
-arg "--exec='source ${srcdir}/if.mail'" \
-arg "--exec=quit" \
-arg "> $MU_FOLDER_DIR/if.out"
......
......@@ -32,7 +32,7 @@ top0 (msgset_t *mspec, mu_message_t msg, void *data)
off_t off;
int lines;
if (util_getenv (&lines, "toplines", Mail_env_number, 1)
if (mailvar_get (&lines, "toplines", mailvar_type_number, 1)
|| lines < 0)
return 1;
......
......@@ -27,7 +27,7 @@ mail_unset (int argc, char **argv)
{
if (argc < 2)
{
util_printenv (0);
mailvar_print (0);
return 0;
}
else
......
......@@ -34,8 +34,6 @@
#endif
#include <mu_asprintf.h>
mu_list_t environment = NULL;
/*
* expands command into its command and arguments, then runs command
* cmd is the command to parse and run
......@@ -269,13 +267,14 @@ util_help (void *table, size_t nmemb, size_t size, const char *word)
FILE *out = stdout;
char *p;
if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "crt", mailvar_type_boolean, 0) == 0)
out = popen (getenv ("PAGER"), "w");
for (p = table, i = 0; i < nmemb; i++, p += size)
{
struct mail_command *cp = (struct mail_command *)p;
if (cp->synopsis == NULL)
continue;
fprintf (out, "%s\n", cp->synopsis);
}
......@@ -288,7 +287,7 @@ util_help (void *table, size_t nmemb, size_t size, const char *word)
{
int status = 0;
struct mail_command *cp = util_find_entry (table, nmemb, size, word);
if (cp)
if (cp && cp->synopsis)
fprintf (stdout, "%s\n", cp->synopsis);
else
{
......@@ -385,7 +384,7 @@ util_screen_lines ()
int screen;
size_t n;
if (util_getenv (&screen, "screen", Mail_env_number, 0) == 0)
if (mailvar_get (&screen, "screen", mailvar_type_number, 0) == 0)
return screen;
n = util_getlines();
util_do_command ("set screen=%d", n);
......@@ -398,7 +397,7 @@ util_screen_columns ()
int cols;
size_t n;
if (util_getenv (&cols, "columns", Mail_env_number, 0) == 0)
if (mailvar_get (&cols, "columns", mailvar_type_number, 0) == 0)
return cols;
n = util_getcols();
util_do_command ("set columns=%d", n);
......@@ -410,299 +409,18 @@ util_get_crt ()
{
int lines;
if (util_getenv (&lines, "crt", Mail_env_number, 0) == 0)
if (mailvar_get (&lines, "crt", mailvar_type_number, 0) == 0)
return lines;
else if (util_getenv (NULL, "crt", Mail_env_boolean, 0) == 0)
else if (mailvar_get (NULL, "crt", mailvar_type_boolean, 0) == 0)
return util_getlines ();
return 0;
}
/* Functions for dealing with internal environment variables */
/* Retrieve the value of a specified variable of given type.
The value is stored in the location pointed to by PTR variable.
VARIABLE and TYPE specify the variable name and type. If the
variable is not found and WARN is not null, the warning message
is issued.
Return value is 0 if the variable is found, 1 otherwise.
If PTR is not NULL, it must point to
int if TYPE is Mail_env_number or Mail_env_boolean
const char * if TYPE is Mail_env_string.
Passing PTR=NULL may be used to check whether the variable is set
without retrieving its value. */
int
util_getenv (void *ptr, const char *variable, mail_env_data_t type, int warn)
{
struct mail_env_entry *env = util_find_env (variable, 0);
if (!mail_env_entry_is_set (env) || env->type != type)
{
if (warn)
util_error (_("No value set for \"%s\""), variable);
return 1;
}
if (ptr)
switch (type)
{
case Mail_env_string:
*(char**)ptr = env->value.string;
break;
case Mail_env_number:
*(int*)ptr = env->value.number;
break;
case Mail_env_boolean:
*(int*)ptr = env->value.bool;
break;
default:
break;
}
return 0;
}
static int
env_comp (const void *a, const void *b)
{
const struct mail_env_entry *epa = a;
const struct mail_env_entry *epb = b;
return strcmp (epa->var, epb->var);
}
/* Find environment entry var. If not found and CREATE is not null, then
create the (unset and untyped) variable */
struct mail_env_entry *
util_find_env (const char *var, int create)
{
struct mail_env_entry entry, *p;
if (strcmp (var, "ask") == 0)
entry.var = "asksub";
else
entry.var = var;
if (environment == NULL)
{
mu_list_create (&environment);
mu_list_set_comparator (environment, env_comp);
}
if (mu_list_locate (environment, &entry, (void**)&p))
{
if (!create)
return 0;
p = xmalloc (sizeof *p);
p->var = xstrdup (entry.var);
mu_list_prepend (environment, p);
p->set = 0;
p->type = Mail_env_whatever;
p->value.number = 0;
}
return p;
}
struct var_iterator
{
const char *prefix;
int prefixlen;
mu_iterator_t itr;
};
const char *
var_iterate_next (var_iterator_t itr)
{
struct mail_env_entry *ep;
while (!mu_iterator_is_done (itr->itr))
{
if (mu_iterator_current (itr->itr, (void **)&ep))
return NULL;
mu_iterator_next (itr->itr);
if (strlen (ep->var) >= itr->prefixlen
&& strncmp (ep->var, itr->prefix, itr->prefixlen) == 0)
return ep->var;
}
return NULL;
}
const char *
var_iterate_first (const char *prefix, var_iterator_t *pitr)
{
if (environment)
{
var_iterator_t itr = xmalloc (sizeof *itr);
itr->prefix = prefix;
itr->prefixlen = strlen (prefix);
mu_list_get_iterator (environment, &itr->itr);
mu_iterator_first (itr->itr);
*pitr = itr;
return var_iterate_next (itr);
}
*pitr = NULL;
return NULL;
}
void
var_iterate_end (var_iterator_t *itr)
{
mu_iterator_destroy (&(*itr)->itr);
free (*itr);
*itr = NULL;
}
/* print the environment */
static int
envp_comp (const void *a, const void *b)
{
struct mail_env_entry * const *epa = a;
struct mail_env_entry * const *epb = b;
return strcmp ((*epa)->var, (*epb)->var);
}
void
util_printenv (int set)
{
struct mail_env_entry **ep;
size_t i, count = 0;
mu_list_count (environment, &count);
ep = xcalloc (count, sizeof *ep);
mu_list_to_array (environment, (void**) ep, count, NULL);
qsort (ep, count, sizeof *ep, envp_comp);
for (i = 0; i < count; i++)
{
switch (ep[i]->type)
{
case Mail_env_number:
fprintf (ofile, "%s=%d", ep[i]->var, ep[i]->value.number);
break;
case Mail_env_string:
fprintf (ofile, "%s=\"%s\"", ep[i]->var, ep[i]->value.string);
break;
case Mail_env_boolean:
if (!ep[i]->value.bool)
fprintf (ofile, "no");
fprintf (ofile, "%s", ep[i]->var);
break;
case Mail_env_whatever:
fprintf (ofile, "%s %s", ep[i]->var, _("oops?"));
}
fprintf (ofile, "\n");
}
free (ep);
}
/* Initialize environment entry: clear set indicator and free any memory
associated with the data */
void
util_mail_env_free (struct mail_env_entry *ep)
{
if (!mail_env_entry_is_set (ep))
return;
switch (ep->type)
{
case Mail_env_string:
free (ep->value.string);
ep->value.string = NULL;
break;
default:
break;
}
ep->set = 0;
}
/* Set environement
The util_setenv() function adds the variable name to the envi-
ronment with the value value, if name does not already
exist. If name does exist in the environment, then its
value is changed to value if overwrite is non-zero; if
overwrite is zero, then the value of name is not changed.
A side effect of the code is if value is null the variable name
will be unset. */
int
util_setenv (const char *variable, void *value, mail_env_data_t type,
int overwrite)
{
struct mail_env_entry *ep = util_find_env (variable, 1);
if (ep->set && !overwrite)
return 0;
util_mail_env_free (ep);
ep->type = type;
if (value)
{
ep->set = 1;
switch (type)
{
case Mail_env_number:
ep->value.number = *(int*)value;
break;
case Mail_env_string:
ep->value.string = strdup (value);
break;
case Mail_env_boolean:
ep->value.bool = *(int*)value;
break;
default:
abort();
}
}
/* Special handling for some variables */
if (strcmp (variable, "replyregex") == 0)
{
int rc;
char *err;
if ((rc = mu_unre_set_regex (value, 0, &err)))
{
fprintf (stderr, "%s", mu_strerror (rc));
if (err)
{
fprintf (stderr, "%s", err);
free (err);
}
fprintf (stderr, "\n");
}
}
else if (strcmp (variable, "decode-fallback") == 0)
{
if (mu_set_default_fallback (value))
mu_error (_("Incorrect value for decode-fallback"));
}
else if (strcmp (variable, "screen") == 0)
page_invalidate (1);
return 0;
}
const char *
util_reply_prefix ()
{
char *prefix = "Re: ";
util_getenv (&prefix, "replyprefix", Mail_env_string, 0);
mailvar_get (&prefix, "replyprefix", mailvar_type_string, 0);
return prefix;
}
......@@ -760,7 +478,7 @@ util_folder_path (const char *name)
char *tmp;
char *p;
if (util_getenv (&folder, "folder", Mail_env_string, 1))
if (mailvar_get (&folder, "folder", mailvar_type_string, 1))
return NULL;
if (!name)
......@@ -981,7 +699,7 @@ util_outfolder_name (char *str)
break;
default:
if (util_getenv (&outfolder, "outfolder", Mail_env_string, 0) == 0)
if (mailvar_get (&outfolder, "outfolder", mailvar_type_string, 0) == 0)
{
char *ns = NULL;
asprintf (&ns, "%s/%s", outfolder, str);
......@@ -1002,7 +720,7 @@ util_save_outgoing (mu_message_t msg, char *savefile)
{
char *record;
if (util_getenv (&record, "record", Mail_env_string, 0) == 0)
if (mailvar_get (&record, "record", mailvar_type_string, 0) == 0)
{
int rc;
mu_mailbox_t outbox;
......@@ -1256,7 +974,7 @@ util_header_expand (mu_header_t *phdr)
while (*p && mu_isspace (*p))
p++;
/* If inplacealiases was set, the value was already expanded */
if (util_getenv (NULL, "inplacealiases", Mail_env_boolean, 0))
if (mailvar_get (NULL, "inplacealiases", mailvar_type_boolean, 0))
exp = alias_expand (p);
rc = mu_address_create (&new_addr, exp ? exp : p);
if (rc)
......@@ -1379,7 +1097,7 @@ util_rfc2047_decode (char **value)
char *tmp;
int rc;
if (!*value || util_getenv (&charset, "charset", Mail_env_string, 0))
if (!*value || mailvar_get (&charset, "charset", mailvar_type_string, 0))
return;
if (mu_c_strcasecmp (charset, "auto") == 0)
......@@ -1415,7 +1133,7 @@ util_rfc2047_decode (char **value)
rc = mu_rfc2047_decode (charset, *value, &tmp);
if (rc)
{
if (util_getenv (NULL, "verbose", Mail_env_boolean, 0) == 0)
if (mailvar_get (NULL, "verbose", mailvar_type_boolean, 0) == 0)
mu_error (_("Cannot decode line `%s': %s"), *value, mu_strerror (rc));
}
else
......