]> granicus.if.org Git - neomutt/commitdiff
Add setenv/unsetenv commands.
authorDavid Champion <dgc@bikeshed.us>
Mon, 12 Dec 2016 02:56:59 +0000 (18:56 -0800)
committerRichard Russon <rich@flatcap.org>
Fri, 30 Dec 2016 20:05:36 +0000 (20:05 +0000)
These can be used to add and remove environment variables passed to
children via mutt_system().

Commited by Kevin McCarthy with some cleanup.

doc/manual.xml.head
init.c
init.h
main.c
system.c

index c5a83d450bfa68a4a3bfc7c906b52472d41a566a..0f2b2ba577166a9398ec9cbadc73046f8caa3955 100644 (file)
@@ -6480,6 +6480,24 @@ if the mailbox shortcut results in an empty regexp.
 
 </sect1>
 
+<sect1 id="setenv">
+<title>Managing the Environment</title>
+
+<para>
+You can alter the environment that Mutt passes on to its child processes
+using the <quote>setenv</quote> and <quote>unsetenv</quote> operators.
+(N.B. These follow Mutt-style syntax, not shell-style!)  You can also
+query current environment values by prefixing a <quote>?</quote> character.
+</para>
+
+<screen>
+setenv TERM vt100
+setenv ORGANIZATION "The Mutt Development Team"
+unsetenv DISPLAY
+setenv ?LESS
+</screen>
+</sect1>
+
 <sect1 id="query">
 <title>External Address Queries</title>
 
@@ -14983,6 +15001,23 @@ The following are the commands understood by Mutt:
 </cmdsynopsis>
 </listitem>
 
+<listitem>
+  <cmdsynopsis>
+    <command><link linkend="setenv">setenv</link></command>
+    <arg choice="plain">
+      <replaceable class="parameter">[?]variable</replaceable>
+    </arg>
+    <arg choice="opt">
+      <replaceable class="parameter">value</replaceable>
+    </arg>
+
+    <command><link linkend="setenv">unsetenv</link></command>
+    <arg choice="plain">
+      <replaceable class="parameter">variable</replaceable>
+    </arg>
+  </cmdsynopsis>
+</listitem>
+
 <listitem>
 <cmdsynopsis>
 <command><link linkend="sidebar-whitelist">sidebar_whitelist</link></command>
diff --git a/init.c b/init.c
index ee271538c827d186bcf6d0eb4e8325578d0a2e91..e3e33f80e1ba2c7ef827ae0bf8b92de63660797c 100644 (file)
--- a/init.c
+++ b/init.c
@@ -85,6 +85,8 @@ static char **nm_tags;
 #endif
 
 
+extern char **envlist;
+
 static void toggle_quadoption (int opt)
 {
   int n = opt/4;
@@ -1830,6 +1832,133 @@ static int check_charset (struct option_t *opt, const char *val)
   return rc;
 }
 
+static int parse_setenv(BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
+{
+  int query, unset, len;
+  char work[LONG_STRING];
+  char **save, **envp = envlist;
+  int count = 0;
+
+  query = 0;
+  unset = data & MUTT_SET_UNSET;
+
+  if (!MoreArgs (s))
+  {
+    strfcpy (err->data, _("too few arguments"), err->dsize);
+    return -1;
+  }
+
+  if (*s->dptr == '?')
+  {
+    query = 1;
+    s->dptr++;
+  }
+
+  /* get variable name */
+  mutt_extract_token (tmp, s, MUTT_TOKEN_EQUAL);
+  len = strlen (tmp->data);
+
+  if (query)
+  {
+    int found = 0;
+    while (envp && *envp)
+    {
+      if (!mutt_strncmp (tmp->data, *envp, len))
+      {
+        if (!found)
+        {
+          mutt_endwin (NULL);
+          found = 1;
+        }
+        puts (*envp);
+      }
+      envp++;
+    }
+
+    if (found)
+    {
+      set_option (OPTFORCEREDRAWINDEX);
+      set_option (OPTFORCEREDRAWPAGER);
+      mutt_any_key_to_continue (NULL);
+      return 0;
+    }
+
+    snprintf (err->data, err->dsize, _("%s is unset"), tmp->data);
+    return -1;
+  }
+
+  if (unset)
+  {
+    count = 0;
+    while (envp && *envp)
+    {
+      if (!mutt_strncmp (tmp->data, *envp, len) && (*envp)[len] == '=')
+      {
+        /* shuffle down */
+        save = envp++;
+        while (*envp)
+        {
+          *save++ = *envp++;
+          count++;
+        }
+        *save = NULL;
+        safe_realloc (&envlist, sizeof(char *) * (count+1));
+        return 0;
+      }
+      envp++;
+      count++;
+    }
+    return -1;
+  }
+
+  if (*s->dptr == '=')
+  {
+    s->dptr++;
+    SKIPWS (s->dptr);
+  }
+
+  if (!MoreArgs (s))
+  {
+    strfcpy (err->data, _("too few arguments"), err->dsize);
+    return -1;
+  }
+
+  /* Look for current slot to overwrite */
+  count = 0;
+  while (envp && *envp)
+  {
+    if (!mutt_strncmp (tmp->data, *envp, len) && (*envp)[len] == '=')
+    {
+      FREE (envp);     /* __FREE_CHECKED__ */
+      break;
+    }
+    envp++;
+    count++;
+  }
+
+  /* Format var=value string */
+  strfcpy (work, tmp->data, sizeof(work));
+  len = strlen (work);
+  work[len++] = '=';
+  mutt_extract_token (tmp, s, 0);
+  strfcpy (&work[len], tmp->data, sizeof(work)-len);
+
+  /* If slot found, overwrite */
+  if (*envp)
+    *envp = safe_strdup (work);
+
+  /* If not found, add new slot */
+  else
+  {
+    *envp = safe_strdup (work);
+    count++;
+    safe_realloc (&envlist, sizeof(char *) * (count + 1));
+    envlist[count] = NULL;
+  }
+
+  return 0;
+}
+
 static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
 {
   int query, unset, inv, reset, r = 0;
diff --git a/init.h b/init.h
index 0229bf9b1ddc135a62de8197ff3e628afd3b56c0..e146a66baaed94610e912fcf62846965106ad831 100644 (file)
--- a/init.h
+++ b/init.h
@@ -4334,6 +4334,7 @@ static int parse_ignore (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_unignore (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_source (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_set (BUFFER *, BUFFER *, unsigned long, BUFFER *);
+static int parse_setenv (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_my_hdr (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_unmy_hdr (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_subscribe (BUFFER *, BUFFER *, unsigned long, BUFFER *);
@@ -4423,6 +4424,7 @@ const struct command_t Commands[] = {
   { "send-hook",       mutt_parse_hook,        MUTT_SENDHOOK },
   { "send2-hook",      mutt_parse_hook,        MUTT_SEND2HOOK },
   { "set",             parse_set,              0 },
+  { "setenv",          parse_setenv,           0 },
 #ifdef USE_SIDEBAR
   { "sidebar_whitelist",parse_list,            UL &SidebarWhitelist },
   { "unsidebar_whitelist",parse_unlist,                UL &SidebarWhitelist },
@@ -4446,6 +4448,7 @@ const struct command_t Commands[] = {
   { "unmy_hdr",                parse_unmy_hdr,         0 },
   { "unscore",         mutt_parse_unscore,     0 },
   { "unset",           parse_set,              MUTT_SET_UNSET },
+  { "unsetenv",                parse_setenv,           MUTT_SET_UNSET },
   { "unsubscribe",     parse_unsubscribe,      0 },
   { NULL,              NULL,                   0 }
 };
diff --git a/main.c b/main.c
index 12c29e7f802251a9e877d7fd186c3a04dc6fa5bd..1958c98f8d85cd744c55959a0efaf7b873aa44ef 100644 (file)
--- a/main.c
+++ b/main.c
@@ -70,6 +70,8 @@
 #include "nntp.h"
 #endif
 
+char **envlist;
+
 void mutt_exit (int code)
 {
   mutt_endwin (NULL);
@@ -177,7 +179,7 @@ init_extended_keys();
 #define MUTT_NEWS    (1<<5)    /* -g and -G */
 #endif
 
-int main (int argc, char **argv)
+int main (int argc, char **argv, char **environ)
 {
   char folder[_POSIX_PATH_MAX] = "";
   char *subject = NULL;
@@ -225,6 +227,17 @@ int main (int argc, char **argv)
   memset (Options, 0, sizeof (Options));
   memset (QuadOptions, 0, sizeof (QuadOptions));
 
+  /* Init envlist */
+  {
+    char **srcp, **dstp;
+    int count = 0;
+    for (srcp = environ; srcp && *srcp; srcp++)
+      count++;
+    envlist = safe_calloc(count+1, sizeof(char *));
+    for (srcp = environ, dstp = envlist; srcp && *srcp; srcp++, dstp++)
+      *dstp = safe_strdup(*srcp);
+  }
+
   for (optind = 1; optind < double_dash; )
   {
     /* We're getopt'ing POSIXLY, so we'll be here every time getopt()
index 36b80fb823c9efa8390c0038bd491ca882616f6c..97dc2a8e79732c47398e0d9d8f5115f10f6da44d 100644 (file)
--- a/system.c
+++ b/system.c
@@ -32,6 +32,8 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+extern char **envlist;
+
 int _mutt_system (const char *cmd, int flags)
 {
   int rc = -1;
@@ -114,7 +116,7 @@ int _mutt_system (const char *cmd, int flags)
     sigaction (SIGTSTP, &act, NULL);
     sigaction (SIGCONT, &act, NULL);
 
-    execl (EXECSHELL, "sh", "-c", cmd, NULL);
+    execle (EXECSHELL, "sh", "-c", cmd, NULL, envlist);
     _exit (127); /* execl error */
   }
   else if (thepid != -1)