Commit 375ffa14 375ffa14056f4165c9674fa94c243bd632c43742 by Sergey Poznyakoff

ali: executable file inclusion.

The "< file" construct tests if file is executable and begins with
the shell interpreter magic (#!/ or #! /).  If so, this file is
executed and its output is collected.  This provides a way for
building aliases on the fly.

* mh/mh_alias.l (buffer_ctx) <exec_p>: New member.
(exec_p): New static variable.
(push_source): If the file is executable and begins with
the "#!/" magic, run it and collect its output.
(pop_source): Use exec_p to decide how to close the file.
* mh/tests/ali.at: Test executable file inclusion.
* NEWS: Update.
1 parent efa51304
GNU mailutils NEWS -- history of user-visible changes. 2012-11-12
GNU mailutils NEWS -- history of user-visible changes. 2013-02-16
Copyright (C) 2002-2012 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -203,6 +203,14 @@ option:
"yes", the mailbox will be truncated after successful processing.
If BOOL is "no", the source mailbox will not be truncated.
** MH aliases
The "< FILE" construct has been extended to allow for building the
list of aliases on the fly. If FILE is an executable file and its
first line begins with a shell interpreter magic (#!/ or #! /), then
instead of being included, such file is run using "/bin/sh -c", its
output is collected and included in the aliases.
** mailutils-config is deprecated.
Use `mu cflags' and `mu ldflags' instead. The mailutils-config is
......
......@@ -219,10 +219,12 @@ struct buffer_ctx {
int line;
ino_t i_node;
FILE *yyin;
int exec_p;
LEX_BUFFER_STATE state;
};
static struct buffer_ctx *context_stack;
static int exec_p;
static struct buffer_ctx *
ctx_lookup (ino_t ino)
......@@ -242,7 +244,8 @@ push_source (const char *name, int fail)
struct buffer_ctx *ctx;
struct stat st;
char *filename;
int ex = 0;
filename = mh_expand_name (NULL, name, 0);
if (stat (filename, &st))
{
......@@ -251,7 +254,7 @@ push_source (const char *name, int fail)
free (filename);
return 1;
}
if (ali_filename && st.st_ino == ali_source_inode)
{
ali_parse_error (_("recursive inclusion"));
......@@ -279,12 +282,35 @@ push_source (const char *name, int fail)
free (filename);
return 1;
}
if (access (filename, X_OK) == 0)
{
char sig[4];
if (fread (sig, sizeof(sig), 1, fp) == 1 &&
(memcmp(sig, "#!/", 3) == 0 ||
memcmp(sig, "#! /", 4) == 0))
{
ex = 1;
fclose (fp);
fp = popen (filename, "r");
if (!fp)
{
ali_parse_error (_("can't execute `%s': %s"),
filename, strerror (errno));
free (filename);
return 1;
}
}
else
rewind (fp);
}
/* Push current context */
if (ali_filename)
{
ctx = mu_alloc (sizeof (*ctx));
ctx->filename = ali_filename;
ctx->exec_p = exec_p;
ctx->line = ali_line_num;
ctx->i_node = ali_source_inode;
ctx->yyin = yyin;
......@@ -307,6 +333,7 @@ push_source (const char *name, int fail)
ali_filename = filename;
ali_line_num = 1;
ali_source_inode = st.st_ino;
exec_p = ex;
return 0;
}
......@@ -316,7 +343,7 @@ pop_source ()
struct buffer_ctx *ctx;
if (yyin)
fclose (yyin);
(exec_p ? pclose : fclose) (yyin);
#ifndef FLEX_SCANNER
lex_delete_buffer (current_buffer);
#endif
......@@ -332,6 +359,7 @@ pop_source ()
ali_filename = context_stack->filename;
ali_line_num = context_stack->line + 1; /* < line did not increment it */
ali_source_inode = context_stack->i_node;
exec_p = context_stack->exec_p;
RESTORE_BUFFER_STATE (context_stack->state);
ctx = context_stack->prev;
free (context_stack);
......
......@@ -108,15 +108,19 @@ ali -list -a ./mh_aliases everybody
[0],
[expout])
MH_CHECK([ali: simple aliases],[ali00],[
MH_CHECK([ali: executable file inlcusion],[ali02 ali-xinclude],[
AT_DATA([Mail/ali.sh],[#! /bin/sh
echo "admin: gray, jeff"
])
chmod +x Mail/ali.sh
AT_DATA([mh_aliases],[
devel: gray, polak
admin: gray, jeff
devel: gray, polak, admin
<ali.sh
])
ali -a ./mh_aliases devel
],
[0],
[gray, polak
[gray, polak, gray, jeff
])
m4_popdef[MH_KEYWORDS])
......