commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg-290-g61295ae
Date: Sat, 11 Jul 2009 16:17:15 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=61295ae0e724c62ac016dfc374d6064c63270288

The branch, master has been updated
       via  61295ae0e724c62ac016dfc374d6064c63270288 (commit)
       via  f6b40b8d77c08636e90ae23b86dd01f7e70f080e (commit)
       via  4b073831ad39f3dd15a8bed93ffc026c5f9830f3 (commit)
      from  181e0c84c1f0bd3d18bc39a9ac6df3c5dcedf3b5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 61295ae0e724c62ac016dfc374d6064c63270288
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Jul 11 19:16:33 2009 +0300

    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.

commit f6b40b8d77c08636e90ae23b86dd01f7e70f080e
Merge: 4b073831ad39f3dd15a8bed93ffc026c5f9830f3 
181e0c84c1f0bd3d18bc39a9ac6df3c5dcedf3b5
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat Jul 11 19:13:07 2009 +0300

    Merge branch 'master' of ssh://address@hidden/srv/git/mailutils

commit 4b073831ad39f3dd15a8bed93ffc026c5f9830f3
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Jul 9 08:47:28 2009 +0300

    Minor fixes.
    
    * libmu_auth/ldap.c: Include mailutils/cstr.h.
    * libmu_auth/sql.c:  Likewise.
    * mimeview/mimetypes.y: Use mu_tolower, instead of tolower.

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

Summary of changes:
 NEWS                       |   40 +++-
 doc/texinfo/programs.texi  |  198 +++++++++++-
 libmu_auth/ldap.c          |    1 +
 libmu_auth/sql.c           |    2 +-
 mail/Makefile.am           |    2 +
 mail/alias.c               |    2 +-
 mail/decode.c              |   10 +-
 mail/delete.c              |    2 +-
 mail/envelope.c            |   51 +++
 mail/escape.c              |   32 +--
 mail/file.c                |    2 +-
 mail/folders.c             |    2 +-
 mail/from.c                |   74 +++--
 mail/if.c                  |    2 +-
 mail/mail.c                |   40 ++--
 mail/mail.h                |   79 +++---
 mail/mailline.c            |   28 +--
 mail/mailvar.c             |  763 ++++++++++++++++++++++++++++++++++++++++++++
 mail/msgset.y              |    4 +-
 mail/pipe.c                |    4 +-
 mail/print.c               |    7 +-
 mail/quit.c                |    6 +-
 mail/reply.c               |    4 +-
 mail/send.c                |   40 ++--
 mail/set.c                 |   12 +-
 mail/shell.c               |    7 +-
 mail/table.c               |    8 +-
 mail/testsuite/mail/if.exp |   10 +-
 mail/top.c                 |    2 +-
 mail/unset.c               |    2 +-
 mail/util.c                |  312 +-----------------
 mimeview/mimetypes.y       |    2 +-
 32 files changed, 1247 insertions(+), 503 deletions(-)
 create mode 100644 mail/envelope.c
 create mode 100644 mail/mailvar.c

diff --git a/NEWS b/NEWS
index 8cd6cda..29bb08a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-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
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index 15cad8e..1c21a52 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -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}.
 
address@hidden 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.:
+
address@hidden
+# 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
address@hidden smallexample
+
+If @code{variable-pretty-print} is not set, only the settings are
+shown, e.g.:
+
address@hidden
+ask
+askcc
+charset="auto"
+columns=80
address@hidden smallexample
+
address@hidden variable, mail command
+A special command is provided to list all internal @command{mail}
+variables:
+
address@hidden
+variable address@hidden
address@hidden 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:
+
address@hidden
+& 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
address@hidden 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
address@hidden append
address@hidden: Boolean, Read-Only
address@hidden: True
address@hidden 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.
 
address@hidden
 @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.
+
address@hidden
 
 @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
 
address@hidden debug
address@hidden: Boolean
address@hidden: Unset
address@hidden debug, mail variable
+
+This variable is not used.  It exists for compatibility with other
address@hidden 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.
 
address@hidden
address@hidden fromfield
address@hidden: Boolean.
address@hidden: True.
+
+By default the sender address is taken from the @samp{From} header.
+Unsetting this variable tells @command{mail} to obtain it from the
address@hidden envelope, instead.
+
address@hidden
+
 @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.
 
address@hidden keep
address@hidden: Boolean, Read-Only
address@hidden: True
address@hidden 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
address@hidden: String.
address@hidden: 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:
+
address@hidden @asis
address@hidden headers
+The program is started with the @option{--headers} (@option{-H}) command
+line option (@pxref{Invoking Mail}).
+
address@hidden exist
+The program is started with the @option{--exist} (@option{-e}) command
+line option (@pxref{Invoking Mail}).
+
address@hidden print
+The program is started with the @option{--print} (@option{-p}) command
+line option (@pxref{Invoking Mail}).
+
address@hidden read
+The progran operates in read mode. This is the default.
+
address@hidden send
+The program operates in send mode. This means it was given one or more
+recipient addresses in the command line.
address@hidden table
 
 @item nullbody
 @* Type: Boolean
@@ -3732,6 +3847,13 @@ outputs something on its standard output or error:
 @end group
 @end smallexample
 
address@hidden showenvelope
address@hidden: Boolean
address@hidden: Unset
+
+If this variable is set, the @code{print} command will include the
address@hidden 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.
 
address@hidden onehop
address@hidden: Boolean
address@hidden: Unset
address@hidden onehop, mail variable
+
+This variable is not used.  It exists for compatibility with other
address@hidden 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.
 
address@hidden quiet
address@hidden: Boolean
address@hidden: Unset
address@hidden quiet, mail variable
+
+This variable is not used.  It exists for compatibility with other
address@hidden 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}.
 
address@hidden readonly
address@hidden: Boolean
address@hidden: False
address@hidden readonly, mail variable
+
+When set, mailboxes are opened in readonly mode.  In this mode, any
address@hidden commands that alter the contents of the mailbox are
+disabled.  These commands include, but are not limited to: 
address@hidden, @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.
+
address@hidden sendwait
address@hidden: Boolean
address@hidden: Unset
address@hidden sendwait, mail variable
+
+This variable is not used.  It exists for compatibility with other
address@hidden implementations and for future use.
+
address@hidden showto
address@hidden: Boolean
address@hidden: False
address@hidden 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.
 
address@hidden variable-strict
address@hidden varstrict
address@hidden: Boolean.
address@hidden: 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,
address@hidden prints a warning.
+
address@hidden and Unsetting the Variables}.
+
address@hidden variable-pretty-print
address@hidden varpp
address@hidden: Boolean.
address@hidden: 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.
diff --git a/libmu_auth/ldap.c b/libmu_auth/ldap.c
index e3cda49..f6616b4 100644
--- a/libmu_auth/ldap.c
+++ b/libmu_auth/ldap.c
@@ -24,6 +24,7 @@
 #include <ctype.h>
 
 #include <mailutils/mu_auth.h>
+#include <mailutils/cstr.h>
 
 #ifdef WITH_LDAP
 #include "mailutils/argcv.h"
diff --git a/libmu_auth/sql.c b/libmu_auth/sql.c
index adb38fc..2f2b85d 100644
--- a/libmu_auth/sql.c
+++ b/libmu_auth/sql.c
@@ -44,7 +44,6 @@
 #include <mailutils/list.h>
 #include <mailutils/iterator.h>
 #include <mailutils/mailbox.h>
-#include <mailutils/sql.h>
 #include <mailutils/mu_auth.h>
 #include <mailutils/error.h>
 #include <mailutils/errno.h>
@@ -52,6 +51,7 @@
 #include <mailutils/mutil.h>
 #include <mailutils/sql.h>
 #include <mailutils/vartab.h>
+#include <mailutils/cstr.h>
 #include "sql.h"
 
 #ifdef USE_SQL
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 7b7682c..a47694b 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -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\
diff --git a/mail/alias.c b/mail/alias.c
index 515f890..613c17a 100644
--- a/mail/alias.c
+++ b/mail/alias.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;
diff --git a/mail/decode.c b/mail/decode.c
index 159f413..369ed76 100644
--- a/mail/decode.c
+++ b/mail/decode.c
@@ -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);
diff --git a/mail/delete.c b/mail/delete.c
index 07e853a..83dae90 100644
--- a/mail/delete.c
+++ b/mail/delete.c
@@ -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;
diff --git a/mail/envelope.c b/mail/envelope.c
new file mode 100644
index 0000000..24d9391
--- /dev/null
+++ b/mail/envelope.c
@@ -0,0 +1,51 @@
+/* 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);
+}
diff --git a/mail/escape.c b/mail/escape.c
index a95528a..e44283e 100644
--- a/mail/escape.c
+++ b/mail/escape.c
@@ -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)
     {
diff --git a/mail/file.c b/mail/file.c
index 2230438..803bb86 100644
--- a/mail/file.c
+++ b/mail/file.c
@@ -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.");
diff --git a/mail/folders.c b/mail/folders.c
index 379bbfe..1eaedf4 100644
--- a/mail/folders.c
+++ b/mail/folders.c
@@ -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] != '~')
diff --git a/mail/from.c b/mail/from.c
index a148d3c..383ae56 100644
--- a/mail/from.c
+++ b/mail/from.c
@@ -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;
diff --git a/mail/if.c b/mail/if.c
index bd74607..f94f79a 100644
--- a/mail/if.c
+++ b/mail/if.c
@@ -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)
diff --git a/mail/mail.c b/mail/mail.c
index 3ebf90b..ff98d9c 100644
--- a/mail/mail.c
+++ b/mail/mail.c
@@ -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");
diff --git a/mail/mail.h b/mail/mail.h
index 9883250..cc9a4a7 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -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
diff --git a/mail/mailline.c b/mail/mailline.c
index 863c8e1..4ed1c3a 100644
--- a/mail/mailline.c
+++ b/mail/mailline.c
@@ -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;
diff --git a/mail/mailvar.c b/mail/mailvar.c
new file mode 100644
index 0000000..6550b39
--- /dev/null
+++ b/mail/mailvar.c
@@ -0,0 +1,763 @@
+/* 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"
+
+#define MAILVAR_ALIAS  0x0001
+#define MAILVAR_RDONLY 0x0002
+#define MAILVAR_HIDDEN 0x0004
+
+struct mailvar_symbol
+{
+  struct mailvar_variable var;
+  enum mailvar_type type;
+  int flags;
+  char *descr;
+};
+
+mu_list_t mailvar_list = NULL;
+
+struct mailvar_symbol mailvar_tab[] =
+  {
+    /* For compatibility with other mailx implementations.
+       Never used, always true. */
+    { { "append", }, mailvar_type_boolean, MAILVAR_RDONLY,
+      N_("messages saved in mbox are appended to the end rather than 
prepended") },
+    { { "appenddeadletter", }, mailvar_type_boolean, 0,
+      N_("append the contents of canceled letter to dead.letter file") },
+    { { "askbcc", }, mailvar_type_boolean, 0,
+      N_("prompt user for bcc before composing the message") },
+    { { "askcc", }, mailvar_type_boolean, 0, 
+      N_("prompt user for cc before composing the message") },
+    { { "ask", }, mailvar_type_boolean, 0,
+      N_("prompt user for subject before composing the message") },
+    { { "asksub", }, mailvar_type_whatever, MAILVAR_ALIAS, NULL },
+    { { "autoinc", }, mailvar_type_boolean, 0,
+      N_("automatically incorporate newly arrived messages")},
+    { { "autoprint", }, mailvar_type_boolean, 0,
+      N_("delete command behaves like dp") },
+    { { "bang", }, mailvar_type_boolean, 0,
+      N_("replace every occurrence of ! in arguments to the shell command"
+        " with the last executed command") },
+    { { "charset", }, mailvar_type_string, 0,
+      N_("output character set for decoded header fields") },
+    { { "cmd", }, mailvar_type_string, 0,
+      N_("default shell command for pipe") },
+    { { "columns", }, mailvar_type_number, 0,
+      N_("number of columns on terminal screen") },
+    { { "crt", }, mailvar_type_number, 0,
+      N_("if numeric, sets the minimum number of output lines needed "
+        "to engage paging; if boolean, use the height of the terminal "
+        "screen to compute the threshold") },
+    { { "datefield", }, mailvar_type_boolean, 0,
+      N_("get date from the `Date:' header, instead of the envelope") },
+    { { "dot", }, mailvar_type_boolean, 0,
+      N_("input message is terminated with a dot alone on a line") },
+    { { "editheaders", }, mailvar_type_boolean, 0,
+      N_("allow to edit message headers while composing") },
+    { { "emptystart", }, mailvar_type_boolean, 0,
+      N_("start interactive mode if the mailbox is empty") },
+    { { "escape", }, mailvar_type_string, 0,
+      N_("character denoting escapes") },
+    { { "flipr", }, mailvar_type_boolean, 0,
+      N_("swap the meaning of reply and Reply commands") },
+    { { "folder", }, mailvar_type_string, 0,
+      N_("folder directory name") },
+    { { "fromfield", }, mailvar_type_boolean, 0,
+      N_("get sender address from the `From:' header, instead of "
+        "the envelope") },
+    { { "gnu-last-command", }, mailvar_type_boolean, MAILVAR_RDONLY,
+      N_("last executed command line") },
+    { { "header", }, mailvar_type_boolean, 0,
+      N_("run the `headers' command after entering interactive mode") },
+    { { "hold", }, mailvar_type_boolean, 0,
+      N_("hold the read or saved messages in the system mailbox") },
+    { { "ignore", }, mailvar_type_boolean, 0,
+      N_("ignore keyboard interrupts when composing messages") },
+    { { "ignoreeof", }, mailvar_type_boolean, 0,
+      N_("typing the EOF character terminates the letter being composed") },
+    { { "indentprefix", }, mailvar_type_string, 0,
+      N_("string used by the ~m escape for indenting quoted messages") },
+    { { "inplacealiases", }, mailvar_type_boolean, 0,
+      N_("expand aliases in the address header field "
+        "before entering send mode") },
+    /* For compatibility with other mailx implementations.
+       Never used, always true. */
+    { { "keep", }, mailvar_type_boolean, MAILVAR_RDONLY,
+      N_("truncate the user's system mailbox when it is empty") },
+    { { "keepsave", }, mailvar_type_boolean, 0,
+      N_("keep saved messages in system mailbox too") },
+    { { "mailx", }, mailvar_type_boolean, 0,
+      N_("enable mailx compatibility mode") },
+    { { "metamail", }, mailvar_type_boolean, 0,
+      N_("interpret the content of message parts; if set to a string "
+        "specifies the name of the externam metamail command") },
+    { { "metoo", }, mailvar_type_boolean, 0,
+      N_("do not remove sender addresses from the recipient list") },
+    { { "mimenoask", }, mailvar_type_string, 0,
+      N_("a comma-separated list of MIME types for which "
+        "no confirmation is needed before running metamail interpreter") },
+    { { "mode", }, mailvar_type_string, MAILVAR_RDONLY,
+      N_("the name of current operation mode") },
+    { { "nullbody", }, mailvar_type_boolean, 0,
+      N_("accept messages with an empty body") },
+    { { "nullbodymsg", }, mailvar_type_string, 0,
+      N_("display this text when sending a message with empty body") },
+    { { "outfolder", }, mailvar_type_string, 0,
+      N_("keep created files in this folder") },
+    { { "page", }, mailvar_type_boolean, 0,
+      N_("pipe command terminates each message with a linefeed") },
+    { { "prompt", }, mailvar_type_string, 0,
+      N_("command prompt sequence") },
+    { { "quit", }, mailvar_type_boolean, 0,
+      N_("keyboard interrupts terminate the program") },
+    { { "rc", }, mailvar_type_boolean, 0,
+      N_("read the system-wide configuration file upon startup") },
+    { { "readonly", }, mailvar_type_boolean, 0,
+      N_("mailboxes are opened in readonly mode") },
+    { { "record", }, mailvar_type_string, 0,
+      N_("save outgoing messages in this file") },
+    { { "recursivealiases", }, mailvar_type_boolean, 0,
+      N_("recursively expand aliases") },
+    { { "regex", }, mailvar_type_boolean, 0,
+      N_("use regular expressions in message specifications") },
+    { { "replyprefix", }, mailvar_type_string, 0,
+      N_("prefix for the subject line of a reply message") },
+    { { "replyregex", }, mailvar_type_string, 0,
+      N_("regexp for recognizing subject lines of reply messages") },
+    { { "save", }, mailvar_type_boolean, 0,
+      N_("stored aborted messages in the user's dead.file") },
+    { { "screen", }, mailvar_type_number, 0,
+      N_("number of lines on terminal screen") },
+    { { "sendmail", }, mailvar_type_string, 0,
+      N_("URL of the mail transport agent") },
+    /* FIXME: Not yet used. */
+    { { "sendwait", }, mailvar_type_boolean, MAILVAR_HIDDEN, NULL },
+    { { "sign", }, mailvar_type_string, 0,
+      N_("signature for use with the ~a command") },
+    { { "Sign", }, mailvar_type_string, 0,
+      N_("signature for use with the ~A command") },
+    { { "showenvelope", }, mailvar_type_boolean, 0,
+      N_("`print' command includes the SMTP envelope in its output") },
+    { { "showto", }, mailvar_type_boolean, 0,
+      N_("if the message was sent by the user, print its recipient address "
+        "in the header summary") },
+    { { "toplines", }, mailvar_type_number, 0,
+      N_("number of lines to be displayed by `top' or `Top'") },
+    { { "verbose", }, mailvar_type_boolean, 0,
+      N_("verbosely trace the process of message delivery") },
+    { { "xmailer", }, mailvar_type_boolean, 0,
+      N_("add the `X-Mailer' header to the outgoing messages") },
+
+    { { "variable-pretty-print", }, mailvar_type_boolean, 0,
+      N_("print variables with short descriptions") },
+    { { "varpp", }, mailvar_type_whatever, MAILVAR_ALIAS },
+    { { "variable-strict", }, mailvar_type_boolean, 0,
+      N_("perform strict checking when setting options") },
+    { { "varstrict", }, mailvar_type_whatever, MAILVAR_ALIAS },
+
+    /* These will be implemented later */
+    { { "debug", }, mailvar_type_whatever, MAILVAR_HIDDEN, NULL },
+    { { "onehop", }, mailvar_type_whatever, MAILVAR_HIDDEN, NULL },
+
+    { { "quiet", }, mailvar_type_boolean, MAILVAR_HIDDEN,
+      "suppresses the printing of the version when first invoked" },
+    
+    { { NULL }, }
+  };
+
+static int mailvar_symbol_count = sizeof (mailvar_tab) / sizeof 
(mailvar_tab[0]) - 1;
+
+struct mailvar_symbol *
+find_mailvar_symbol (const char *var)
+{
+  struct mailvar_symbol *ep;
+  for (ep = mailvar_tab; ep->var.name; ep++)
+    if (strcmp (ep->var.name, var) == 0)
+      {
+       while ((ep->flags & MAILVAR_ALIAS) && ep > mailvar_tab)
+         ep--;
+       return ep;
+      }
+  return NULL;
+}
+
+static void
+print_descr (FILE *out, char *s, int n, int doc_col, int rmargin, char *pfx)
+{
+  if (!s)
+    return;
+  do
+    {
+      char *p;
+      char *space = NULL;
+
+      if (n == 1 && pfx)
+       n += fprintf (out, "%s", pfx);
+      
+      for (; n < doc_col; n++)
+       fputc (' ', out);
+
+      for (p = s; *p && p < s + (rmargin - doc_col); p++)
+       if (mu_isspace (*p))
+         space = p;
+      
+      if (!space || p < s + (rmargin - doc_col))
+       {
+         fprintf (out, "%s", s);
+         s += strlen (s);
+       }
+      else
+       {
+         for (; s < space; s++)
+           fputc (*s, out);
+         for (; *s && mu_isspace (*s); s++)
+           ;
+       }
+      fputc ('\n', out);
+      n = 1;
+    }
+  while (*s);
+}
+
+/* Functions for dealing with internal mailvar_list variables */
+static int
+mailvar_variable_comp (const void *a, const void *b)
+{
+  const struct mailvar_variable *v1 = a;
+  const struct mailvar_variable *v2 = b;
+
+  return strcmp (v1->name, v2->name);
+}
+
+static int
+mailvar_varptr_comp (const void *a, const void *b)
+{
+  const struct mailvar_variable * const * v1 = a;
+  const struct mailvar_variable * const * v2 = b;
+
+  return strcmp ((*v1)->name, (*v2)->name);
+}
+
+/* Find mailvar_list entry VAR. If not found and CREATE is not NULL, then
+   create the (unset and untyped) variable */
+struct mailvar_variable *
+mailvar_find_variable (const char *name, int create)
+{
+  struct mailvar_symbol *sym;
+  struct mailvar_variable *var;
+  
+  sym = find_mailvar_symbol (name);
+  if (sym)
+    var = &sym->var;
+  else
+    {
+      struct mailvar_variable entry, *p;
+
+      entry.name = (char*)name;
+      /* Store it into the list */
+      if (mailvar_list == NULL)
+       {
+         mu_list_create (&mailvar_list);
+         mu_list_set_comparator (mailvar_list, mailvar_variable_comp);
+       }
+  
+      if (mu_list_locate (mailvar_list, &entry, (void**)&p))
+       {
+         if (!create)
+           return 0;
+         else
+           {
+             p = xmalloc (sizeof *p);
+             p->name = xstrdup (name);
+             mu_list_prepend (mailvar_list, p);
+           }
+       }
+      var = p;
+      var->set = 0;
+      var->type = mailvar_type_whatever;
+      var->value.number = 0;
+    }
+
+  return var;
+}
+
+
+/* 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 mailvar_type_number or mailvar_type_boolean
+   const char *  if TYPE is mailvar_type_string. 
+
+   Passing PTR=NULL may be used to check whether the variable is set
+   without retrieving its value. */
+   
+int
+mailvar_get (void *ptr, const char *variable, enum mailvar_type type, int warn)
+{
+  struct mailvar_variable *var = mailvar_find_variable (variable, 0);
+
+  if (!var->set || var->type != type)
+    {
+      if (warn)
+       util_error (_("No value set for \"%s\""), variable);
+      return 1;
+    }
+  if (ptr)
+    switch (type)
+      {
+      case mailvar_type_string:
+       *(char**)ptr = var->value.string;
+       break;
+
+      case mailvar_type_number:
+       *(int*)ptr = var->value.number;
+       break;
+
+      case mailvar_type_boolean:
+       *(int*)ptr = var->value.bool;
+       break;
+
+      default:
+       break;
+      }
+  
+  return 0;
+}
+
+/* Initialize mailvar_list entry: clear set indicator and free any memory
+   associated with the data */
+void
+mailvar_variable_reset (struct mailvar_variable *var)
+{
+  if (!var->set)
+    return;
+  
+  switch (var->type)
+    {
+    case mailvar_type_string:
+      free (var->value.string);
+      var->value.string = NULL;
+      break;
+             
+    default:
+      break;
+    }
+  var->set = 0;
+}
+
+/* Set environement
+   The  mailvar_set() function adds to the mailvar_list the VARIABLE
+   with the given VALUE, if VARIABLE does not already exist.
+   If it does exist in the mailvar_list, then its value is changed
+   to VALUE if MOPTF_OVERWRITE bit is set in FLAGS, otherwise the
+   value is not changed.
+
+   Unless MOPTF_QUIET bit is set in FLAGS, the function performs
+   semantic check, using the builtin options table.
+ 
+   If VALUE is null the VARIABLE is unset. */
+int
+mailvar_set (const char *variable, void *value, enum mailvar_type type,
+            int flags)
+{
+  struct mailvar_variable *var;
+  
+  if (!(flags & MOPTF_QUIET)
+      && mailvar_get (NULL, "variable-strict", mailvar_type_boolean, 0) == 0)
+    {
+      const struct mailvar_symbol *sym = find_mailvar_symbol (variable);
+
+      if (!sym)
+       mu_diag_output (MU_DIAG_WARNING, _("setting unknown variable %s"),
+                       variable);
+      else if (sym->flags & MAILVAR_RDONLY)
+       {
+         mu_error (_("Cannot set read-only variable %s"),
+                   variable);
+         return 1;
+       }
+    }
+
+  var = mailvar_find_variable (variable, 1);
+
+  if (!var || (var->set && !(flags & MOPTF_OVERWRITE)))
+    return 0;
+
+  mailvar_variable_reset (var);
+  
+  var->type = type;
+  if (value)
+    {
+      var->set = 1;
+      switch (type)
+       {
+       case mailvar_type_number:
+         var->value.number = *(int*)value;
+         break;
+         
+       case mailvar_type_string:
+         var->value.string = strdup (value);
+         break;
+         
+       case mailvar_type_boolean:
+         var->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;
+}
+
+
+size_t
+_mailvar_symbol_count (int set)
+{
+  if (!set)
+    return mailvar_symbol_count;
+  else
+    {
+      struct mailvar_symbol *s;
+      size_t count = 0;
+      for (s = mailvar_tab; s->var.name; s++)
+       if (s->var.set)
+         count++;
+      return count;
+    }
+}
+
+void
+_mailvar_symbol_to_array (int set, struct mailvar_variable **vartab)
+{
+  struct mailvar_symbol *s;
+  for (s = mailvar_tab; s->var.name; s++)
+    if (!set || s->var.set)
+      {
+       *vartab = &s->var;
+       vartab++;
+      }
+}
+
+struct mailvar_variable **
+mailvar_make_array (int set, size_t *pcount)
+{
+  struct mailvar_variable **vartab;
+  size_t count = 0, symcount;
+
+  symcount = _mailvar_symbol_count (set);
+  mu_list_count (mailvar_list, &count);
+  vartab = xcalloc (symcount + count + 1, sizeof *vartab);
+  mu_list_to_array (mailvar_list, (void**) vartab, count, NULL);
+  _mailvar_symbol_to_array (set, vartab + count);
+  count += symcount;
+  qsort (vartab, count, sizeof *vartab, mailvar_varptr_comp);
+  vartab[count] = NULL;
+  if (pcount)
+    *pcount = count;
+  return vartab;
+}
+  
+
+struct mailvar_iterator
+{
+  const char *prefix;
+  int prefixlen;
+  struct mailvar_variable **varptr;
+  size_t varcnt;
+  size_t pos;
+};
+  
+const char *
+mailvar_iterate_next (struct mailvar_iterator *itr)
+{
+  struct mailvar_variable *vp;
+  
+  while (itr->pos < itr->varcnt)
+    {
+      vp = itr->varptr[itr->pos++];
+  
+      if (strlen (vp->name) >= itr->prefixlen
+         && strncmp (vp->name, itr->prefix, itr->prefixlen) == 0)
+       return vp->name;
+    }
+  return NULL;
+}
+
+const char *
+mailvar_iterate_first (int set, const char *prefix, struct mailvar_iterator 
**pitr)
+{
+  struct mailvar_iterator *itr = xmalloc (sizeof *itr);
+  itr->prefix = prefix;
+  itr->prefixlen = strlen (prefix);
+  itr->varptr = mailvar_make_array (set, &itr->varcnt);
+  itr->pos = 0;
+  *pitr = itr;
+  return mailvar_iterate_next (itr);
+}
+
+void
+mailvar_iterate_end (struct mailvar_iterator **pitr)
+{
+  if (pitr && *pitr)
+    {
+      struct mailvar_iterator *itr = *pitr;
+      free (itr->varptr);
+      free (itr);
+      *pitr = NULL;
+    }
+}
+
+void
+mailvar_print (int set)
+{
+  struct mailvar_variable **vartab;
+  FILE *out = ofile;
+  size_t i, count;
+  int pagelines = util_get_crt ();
+  int width = util_getcols ();
+  int prettyprint = mailvar_get (NULL, "variable-pretty-print",
+                                mailvar_type_boolean, 0) == 0;
+  
+  vartab = mailvar_make_array (set, &count);
+
+  if (pagelines && count > pagelines)
+    out = popen (getenv ("PAGER"), "w");
+
+  for (i = 0; i < count; i++)
+    {
+      if (prettyprint)
+       {
+         const struct mailvar_symbol *sym =
+           find_mailvar_symbol (vartab[i]->name);
+
+         if (sym)
+           {
+             if (sym->flags & MAILVAR_HIDDEN)
+               continue;
+             if (sym->flags & MAILVAR_RDONLY)
+               fprintf (out, "# %s:\n", _("Read-only variable"));
+             print_descr (out, gettext (sym->descr), 1, 3, width - 1, "# ");
+           }
+       }
+      switch (vartab[i]->type)
+       {
+       case mailvar_type_number:
+         fprintf (out, "%s=%d", vartab[i]->name, vartab[i]->value.number);
+         break;
+         
+       case mailvar_type_string:
+         fprintf (out, "%s=\"%s\"", vartab[i]->name, vartab[i]->value.string);
+         break;
+         
+       case mailvar_type_boolean:
+         if (!vartab[i]->value.bool)
+           fprintf (out, "no");
+         fprintf (out, "%s", vartab[i]->name);
+         break;
+         
+       case mailvar_type_whatever:
+         fprintf (out, "%s %s", vartab[i]->name, _("oops?"));
+       }
+      fprintf (out, "\n");
+    }
+  free (vartab);
+
+  if (out != ofile)
+    pclose (out);
+}
+
+
+void
+mailvar_variable_format (FILE *fp,
+                        const struct mailvar_variable *var,
+                        const char *defval)
+{
+  if (var)
+    switch (var->type)
+      {
+      case mailvar_type_string:
+       fprintf (fp, "%s", var->value.string);
+       break;
+
+      case mailvar_type_number:
+       fprintf (fp, "%d", var->value.number);
+       break;
+
+      case mailvar_type_boolean:
+       fprintf (fp, "%s", var->set ? "yes" : "no");
+       break;
+
+      default:
+       if (defval)
+         fprintf (fp, "%s", defval);
+       break;
+      }
+}
+
+
+static char *typestr[] =
+  {
+    N_("untyped"),
+    N_("numeric"),
+    N_("string"),
+    N_("boolean")
+  };
+
+static void
+describe_symbol (FILE *out, int width, const struct mailvar_symbol *sym)
+{
+  int n;
+  const struct mailvar_symbol *ali;
+
+  n = fprintf (out, "%s", sym->var.name);
+  for (ali = sym + 1; ali->var.name && ali->flags & MAILVAR_ALIAS; ali++)
+    {
+      size_t len = strlen (ali->var.name) + 2;
+      if (n + len > width)
+       n = fprintf (out, "\n%s", ali->var.name);
+      else
+       n = fprintf (out, ", %s", ali->var.name);
+    }
+  fputc ('\n', out);
+  
+  fprintf (out, _("Type: %s\n"), gettext (typestr[sym->type]));
+  fprintf (out, "%s", _("Current value: "));
+  mailvar_variable_format (out, &sym->var, _("[not set]"));
+
+  if (sym->flags & MAILVAR_RDONLY)
+    fprintf (out, " [%s]", _("read-only"));
+  fputc ('\n', out);
+  
+  print_descr (out, gettext (sym->descr ? sym->descr : N_("Not documented")),
+              1, 1, width - 1, NULL);
+  fputc ('\n', out);
+}
+
+int
+mail_variable (int argc, char **argv)
+{
+  int pagelines = util_get_crt ();
+  int width = util_getcols ();
+  FILE *out = ofile;
+
+  if (pagelines)
+    out = popen (getenv ("PAGER"), "w");
+  
+  if (argc == 1)
+    {
+      struct mailvar_symbol *sym;
+
+      for (sym = mailvar_tab; sym->var.name; sym++)
+       if (!(sym->flags & (MAILVAR_HIDDEN|MAILVAR_ALIAS)))
+         describe_symbol (out, width, sym);
+    }
+  else
+    {
+      int i;
+
+      for (i = 1; i < argc; i++)
+       {
+         struct mailvar_symbol *sym = find_mailvar_symbol (argv[i]);
+         if (!sym)
+           fprintf (out, "%s: unknown\n", argv[i]);
+         else
+           describe_symbol (out, width, sym);
+       }
+    }
+  if (out != ofile)
+    pclose (out);
+  return 0;
+}
+
+
+#ifdef WITH_READLINE
+static char *
+mailvar_generator (int set, const char *text, int state)
+{
+  static struct mailvar_iterator *itr;
+  const char *p;
+  
+  if (!state)
+    p = mailvar_iterate_first (set, text, &itr);
+  else
+    p = mailvar_iterate_next (itr);
+
+  if (!p)
+    {
+      mailvar_iterate_end (&itr);
+      return NULL;
+    }
+  return strdup (p);
+}
+
+static char *
+mailvar_set_generator (const char *text, int state)
+{
+  return mailvar_generator (0, text, state);
+}
+
+static char *
+mailvar_unset_generator (const char *text, int state)
+{
+  return mailvar_generator (1, text, state);
+}
+
+char **
+mailvar_set_compl (int argc, char **argv, int ws)
+{
+  ml_attempted_completion_over ();
+  return rl_completion_matches (ws ? "" : argv[argc-1],
+                               /* Possible values for argv[0] are:
+                                  set, unset, variable */
+                               argv[0][0] == 'u' ? mailvar_unset_generator
+                                                 : mailvar_set_generator);
+}
+
+#endif
diff --git a/mail/msgset.y b/mail/msgset.y
index 138d39b..dbf484f 100644
--- a/mail/msgset.y
+++ b/mail/msgset.y
@@ -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;
diff --git a/mail/pipe.c b/mail/pipe.c
index f864c30..4afe18a 100644
--- a/mail/pipe.c
+++ b/mail/pipe.c
@@ -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);
diff --git a/mail/print.c b/mail/print.c
index c2a07ba..51d77d4 100644
--- a/mail/print.c
+++ b/mail/print.c
@@ -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;
diff --git a/mail/quit.c b/mail/quit.c
index 94e0d04..524ecc7 100644
--- a/mail/quit.c
+++ b/mail/quit.c
@@ -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;
 
diff --git a/mail/reply.c b/mail/reply.c
index 81c49f6..2fc9e97 100644
--- a/mail/reply.c
+++ b/mail/reply.c
@@ -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);
 }
diff --git a/mail/send.c b/mail/send.c
index b427940..e77560f 100644
--- a/mail/send.c
+++ b/mail/send.c
@@ -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;
diff --git a/mail/set.c b/mail/set.c
index 78c0b48..8f51f46 100644
--- a/mail/set.c
+++ b/mail/set.c
@@ -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;
diff --git a/mail/shell.c b/mail/shell.c
index ef296ab..8f7b8e0 100644
--- a/mail/shell.c
+++ b/mail/shell.c
@@ -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 */
   
diff --git a/mail/table.c b/mail/table.c
index fbda87f..3630908 100644
--- a/mail/table.c
+++ b/mail/table.c
@@ -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,
diff --git a/mail/testsuite/mail/if.exp b/mail/testsuite/mail/if.exp
index 18470a9..b5e59ae 100644
--- a/mail/testsuite/mail/if.exp
+++ b/mail/testsuite/mail/if.exp
@@ -1,6 +1,6 @@
 # -*- 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"
diff --git a/mail/top.c b/mail/top.c
index 7343dc7..5b35665 100644
--- a/mail/top.c
+++ b/mail/top.c
@@ -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;
 
diff --git a/mail/unset.c b/mail/unset.c
index dd0152c..fa9cd22 100644
--- a/mail/unset.c
+++ b/mail/unset.c
@@ -27,7 +27,7 @@ mail_unset (int argc, char **argv)
 {
   if (argc < 2)
     {
-      util_printenv (0);
+      mailvar_print (0);
       return 0;
     }
   else
diff --git a/mail/util.c b/mail/util.c
index 0b5cc27..6bd4a97 100644
--- a/mail/util.c
+++ b/mail/util.c
@@ -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
diff --git a/mimeview/mimetypes.y b/mimeview/mimetypes.y
index f46f29e..7e0a934 100644
--- a/mimeview/mimetypes.y
+++ b/mimeview/mimetypes.y
@@ -392,7 +392,7 @@ b_istring (union argument *args)
   for (i = 0; i < str->len; i++)
     {
       int c = getc (mimeview_fp);
-      if (c == EOF || tolower (c) != tolower (str->ptr[i]))
+      if (c == EOF || mu_tolower (c) != mu_tolower (str->ptr[i]))
        return 0;
     }
   return 1;


hooks/post-receive
-- 
GNU Mailutils




reply via email to

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