Re: mutt/2362: my_foo and environment not interpreted correctly with mailboxes and ignore and probably other commands
The following reply was made to PR mutt/2362; it has been noted by GNATS.
From: Rocco Rutte <pdmef@xxxxxxx>
To: bug-any@xxxxxxxxxxxxx
Cc:
Subject: Re: mutt/2362: my_foo and environment not interpreted correctly with
mailboxes and ignore and probably other commands
Date: Sun, 16 Jul 2006 13:48:24 +0000
--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Disposition: inline
Hi,
* michael.tatge@xxxxxx [06-07-16 15:11:46 +0200] wrote:
>I was told the problem lies in mutt_extract_token().
That was me on #mutt. The problem is: in parse_mailboxes() and all other
consumers of mutt_extract_token(). When an environment or mutt variable
is found, it's _complete_ value is returned as just one token.
This means that:
set my_foo="+bar +foo"
mailboxes $my_foo
will make mutt_extract_token return '+bar +foo' as the only token. It
should instead push the results of the expansion back and continue. As
Michael found out, this is done for backtick expansion already.
In the attached patch, I moved the "push result back" code out to a new
function I also used to push the result of environment vars back.
Now this seems to work but needs much more testing and hacking to
resolve infinite loops:
$ export FOO='$FOO'
$ ./mutt -e 'mailboxes $FOO'
bye, Rocco
--
:wq!
--zYM0uCDKw75PZbzx
Content-Type: text/x-patch; charset=us-ascii
Content-Disposition: attachment; filename="patch-init0.diff"
diff --git a/buffy.c b/buffy.c
diff --git a/init.c b/init.c
index a0a5d3d..9b64231 100644
--- a/init.c
+++ b/init.c
@@ -129,6 +129,36 @@ int mutt_option_index (char *s)
return (-1);
}
+static void push_result (BUFFER *dest, BUFFER *tok, BUFFER *result, unsigned
char qc)
+{
+ size_t resultlen;
+ char* ptr;
+
+ /* if we got output, make a new string consiting of the ouptput to be
+ * pushed back plus whatever else was left on the original line;
+ * BUT: If this is inside a quoted string, directly add output to the token
*/
+ if (result->data && qc)
+ {
+ mutt_buffer_addstr (dest, result->data);
+ FREE (&result->data);
+ }
+ else if (result->data)
+ {
+ resultlen = mutt_strlen (result->data);
+ tok->dsize = resultlen + mutt_strlen (tok->dptr) + 1;
+ ptr = safe_malloc (tok->dsize);
+ memcpy (ptr, result->data, resultlen);
+ strcpy (ptr + resultlen, tok->dptr); /* __STRCPY_CHECKED__ */
+ if (tok->destroy)
+ FREE (&tok->data);
+ tok->data = ptr;
+ tok->dptr = ptr;
+ tok->destroy = 1; /* mark that the caller should destroy this data */
+ ptr = NULL;
+ FREE (&result->data);
+ }
+}
+
int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags)
{
char ch;
@@ -220,8 +250,7 @@ int mutt_extract_token (BUFFER *dest, BU
{
FILE *fp;
pid_t pid;
- char *cmd, *ptr;
- size_t expnlen;
+ char *cmd;
BUFFER expn;
int line = 0;
@@ -256,36 +285,18 @@ int mutt_extract_token (BUFFER *dest, BU
fclose (fp);
mutt_wait_filter (pid);
- /* if we got output, make a new string consiting of the shell ouptput
- plus whatever else was left on the original line */
- /* BUT: If this is inside a quoted string, directly add output to
- * the token */
- if (expn.data && qc)
- {
- mutt_buffer_addstr (dest, expn.data);
- FREE (&expn.data);
- }
- else if (expn.data)
- {
- expnlen = mutt_strlen (expn.data);
- tok->dsize = expnlen + mutt_strlen (tok->dptr) + 1;
- ptr = safe_malloc (tok->dsize);
- memcpy (ptr, expn.data, expnlen);
- strcpy (ptr + expnlen, tok->dptr); /* __STRCPY_CHECKED__ */
- if (tok->destroy)
- FREE (&tok->data);
- tok->data = ptr;
- tok->dptr = ptr;
- tok->destroy = 1; /* mark that the caller should destroy this data */
- ptr = NULL;
- FREE (&expn.data);
- }
+ /* result may contain more tokens we need to parse */
+ push_result (dest, tok, &expn, qc);
+
}
else if (ch == '$' && (!qc || qc == '"') && (*tok->dptr == '{' || isalpha
((unsigned char) *tok->dptr)))
{
const char *env = NULL;
char *var = NULL;
int idx;
+ BUFFER expn;
+
+ memset (&expn, 0, sizeof (BUFFER));
if (*tok->dptr == '{')
{
@@ -306,17 +317,21 @@ int mutt_extract_token (BUFFER *dest, BU
if (var)
{
if ((env = getenv (var)) || (env = myvar_get (var)))
- mutt_buffer_addstr (dest, env);
+ mutt_buffer_addstr (&expn, env);
else if ((idx = mutt_option_index (var)) != -1)
{
/* expand settable mutt variables */
char val[LONG_STRING];
if (var_to_string (idx, val, sizeof (val)))
- mutt_buffer_addstr (dest, val);
+ mutt_buffer_addstr (&expn, val);
}
FREE (&var);
}
+
+ /* result may contain more tokens we need to parse */
+ push_result (dest, tok, &expn, qc);
+
}
else
mutt_buffer_addch (dest, ch);
--zYM0uCDKw75PZbzx--