doc/manual.xml.head | 18 ++++++++ init.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ init.h | 3 + main.c | 15 ++++++- system.c | 4 +- 5 files changed, 151 insertions(+), 2 deletions(-)
# HG changeset patch # User David Champion <[email protected]> # Date 1472604759 25200 # Tue Aug 30 17:52:39 2016 -0700 # Node ID be92ca7a461efd7815d5f6b170292798b7c79b3c # Parent 788059e7b1182f283c6d21139beaf9dd0d587035 setenv/unsetenv for altering process environment (to affect children) diff --git a/doc/manual.xml.head b/doc/manual.xml.head --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@ -5769,6 +5769,24 @@ </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> diff --git a/init.c b/init.c --- a/init.c +++ b/init.c @@ -76,6 +76,8 @@ static const char* myvar_get (const char* var); static void myvar_del (const char* var); +extern char **envlist; + static void toggle_quadoption (int opt) { int n = opt/4; @@ -1696,6 +1698,117 @@ 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)) + { + 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 (!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 (!strncmp(tmp->data, *envp, len) && (*envp)[len] == '=') + { + /* shuffle down */ + save = envp++; + while (*envp) { + *save++ = *envp++; + count++; + } + *save = NULL; + envlist = realloc(envlist, sizeof(char *) * (count+1)); + return 0; + } + envp++; + count++; + } + return -1; + } + + /* Look for current slot to overwrite */ + count = 0; + while (envp && *envp) + { + if (!strncmp(tmp->data, *envp, len) && (*envp)[len] == '=') + { + FREE(envp); + break; + } + envp++; + count++; + } + + /* Format var=value string */ + strncpy(work, tmp->data, sizeof(work)); + len = strlen(work); + work[len++] = '='; + mutt_extract_token (tmp, s, 0); + strncpy(&work[len], tmp->data, sizeof(work)-len); + + /* If slot found, overwrite */ + if (*envp) { + *envp = strdup(work); + } + + /* If not found, add new slot */ + else { + *envp = strdup(work); + count++; + envlist = realloc(envlist, sizeof(char *) * (count + 1)); + envlist[count] = NULL; + } + + return 0; + } + + return -1; +} + 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 --- a/init.h +++ b/init.h @@ -3873,6 +3873,7 @@ 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 *); @@ -3945,6 +3946,7 @@ { "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 }, #endif @@ -3964,6 +3966,7 @@ { "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 --- a/main.c +++ b/main.c @@ -105,6 +105,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\ "); +char **envlist; + void mutt_exit (int code) { mutt_endwin (NULL); @@ -565,7 +567,7 @@ #define MUTT_RO (1<<3) /* -R */ #define MUTT_SELECT (1<<4) /* -y */ -int main (int argc, char **argv) +int main (int argc, char **argv, char **environ) { char folder[_POSIX_PATH_MAX] = ""; char *subject = NULL; @@ -613,6 +615,17 @@ 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() diff --git a/system.c b/system.c --- 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 @@ 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)
