summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Varshavchik2017-07-23 23:16:48 -0400
committerSam Varshavchik2017-07-23 23:16:48 -0400
commit4238d38f75d45793521a3b49ba421413d2b53a21 (patch)
tree241d230890014f5e69ae4738cdf0f520dafc1992
parentde2a130974e1a76daa1893e18442154c7fc90321 (diff)
downloadcourier-libs-4238d38f75d45793521a3b49ba421413d2b53a21.tar.bz2
maildrop: add the "system" command.
-rw-r--r--maildrop/filter.C63
-rw-r--r--maildrop/funcs.h1
-rw-r--r--maildrop/lexer.C3
-rw-r--r--maildrop/maildrop.sgml13
-rw-r--r--maildrop/maildropfilter.sgml26
-rw-r--r--maildrop/recipenode.C13
-rw-r--r--maildrop/recipenode.h1
-rw-r--r--maildrop/recipeparse.C8
-rw-r--r--maildrop/token.C1
-rw-r--r--maildrop/token.h1
10 files changed, 125 insertions, 5 deletions
diff --git a/maildrop/filter.C b/maildrop/filter.C
index d59e2ec..abc3872 100644
--- a/maildrop/filter.C
+++ b/maildrop/filter.C
@@ -100,7 +100,7 @@ pid_t pid=fork();
{
if (write(2, p, strlen(p)) < 0 ||
write(2, "\n", 1) < 0)
- ; /* ignore */
+ ; /* ignore */
_exit(100);
}
#if NEED_NONCONST_EXCEPTIONS
@@ -273,3 +273,64 @@ int wait_stat;
return (-1);
return (0);
}
+
+void executesystem(const char *cmd)
+{
+ int devnull=open("/dev/null", O_RDONLY);
+ pid_t pid;
+
+ if (devnull < 0)
+ throw "Cannot open /dev/null";
+
+ pid=fork();
+ if (pid < 0)
+ {
+ close(devnull);
+ throw "Cannot fork.";
+ }
+
+ if (pid == 0)
+ {
+ try
+ {
+ dup2(devnull, 0);
+ close(devnull);
+ subshell(cmd);
+ }
+ catch (const char *p)
+ {
+ if (write(2, p, strlen(p)) < 0 ||
+ write(2, "\n", 1) < 0)
+ ; /* ignore */
+ _exit(100);
+ }
+#if NEED_NONCONST_EXCEPTIONS
+ catch (char *p)
+ {
+ if (write(2, p, strlen(p)) < 0 ||
+ write(2, "\n", 1) < 0)
+ ; /* ignore */
+ _exit(100);
+ }
+#endif
+ catch (...)
+ {
+ _exit(101);
+ }
+ }
+ close(devnull);
+
+int wait_stat;
+
+ while (wait(&wait_stat) != pid)
+ ;
+ wait_stat= WIFEXITED(wait_stat) ? WEXITSTATUS(wait_stat):-1;
+
+ {
+ Buffer name, val;
+
+ val.append( (unsigned long)wait_stat);
+ name="RETURNCODE";
+ SetVar(name, val);
+ }
+}
diff --git a/maildrop/funcs.h b/maildrop/funcs.h
index 3ac3a5e..ad17bac 100644
--- a/maildrop/funcs.h
+++ b/maildrop/funcs.h
@@ -20,6 +20,7 @@ extern int verbose_level;
const char *GetDefaultMailbox(const char *);
int delivery(const char *);
int filter(const char *);
+void executesystem(const char *);
void subshell(const char *);
const char *TempName(); // Return temporary filename
const char *TempName(const char *, unsigned=0); // ... with this prefix.
diff --git a/maildrop/lexer.C b/maildrop/lexer.C
index 99732dd..65e019a 100644
--- a/maildrop/lexer.C
+++ b/maildrop/lexer.C
@@ -41,6 +41,7 @@ void Lexer::token(Token &t)
case Token::tokencc:
case Token::btstring:
case Token::tokenxfilter:
+ case Token::tokensystem:
case Token::dotlock:
case Token::flock:
case Token::logfile:
@@ -346,6 +347,8 @@ missquote:
t.Type(Token::echo);
else if (pattern == "xfilter")
t.Type(Token::tokenxfilter);
+ else if (pattern == "system")
+ t.Type(Token::tokensystem);
else if (pattern == "dotlock")
t.Type(Token::dotlock);
else if (pattern == "flock")
diff --git a/maildrop/maildrop.sgml b/maildrop/maildrop.sgml
index b476d71..ca5beba 100644
--- a/maildrop/maildrop.sgml
+++ b/maildrop/maildrop.sgml
@@ -620,6 +620,13 @@ The <command>logfile</command> command is not allowed in embedded mode.</para>
</listitem>
</varlistentry>
<varlistentry>
+ <term><ulink url="maildropfilter.html#system">system</ulink></term>
+ <listitem>
+<para>
+The <command>system</command> command is not allowed in embedded mode.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><ulink url="maildropfilter.html#to">to</ulink></term>
<listitem>
<para>
@@ -663,8 +670,10 @@ suspended for any additional filter files that are included from
<para>
This allows the system administrator to have a controlled environment for
-running external commands (via the backticks, or the
-<ulink url="maildropfilter.html#xfilter">xfilter</ulink> command).</para>
+running external commands (via the backticks, the
+<ulink url="maildropfilter.html#system">system</ulink>
+or the
+<ulink url="maildropfilter.html#xfilter">xfilter</ulink> commands).</para>
<para>
The name of the file may not contain any periods (so that a creative
diff --git a/maildrop/maildropfilter.sgml b/maildrop/maildropfilter.sgml
index 4d91abc..c97aeec 100644
--- a/maildrop/maildropfilter.sgml
+++ b/maildrop/maildropfilter.sgml
@@ -511,7 +511,9 @@ MAILBOX="${HOME-WORD}/Mailbox"
</para></listitem></varlistentry>
<varlistentry><term><varname>RETURNCODE</varname></term><listitem><para>This variable is set when <command>maildrop</command>
- runs the <ulink url="#xfilter">xfilter</ulink> command, or a command that's
+ runs the
+ <ulink url="#system">system</ulink> command,
+ <ulink url="#xfilter">xfilter</ulink> command, or a command that's
specified within a pair of backtick characters ( command substitution ).
The <varname>RETURNCODE</varname> variable will be set to the exit code of the
command, after it completes.
@@ -1485,6 +1487,28 @@ log <replaceable>expression</replaceable>
</refsect3>
<refsect3>
+ <title>system - execute a system command</title>
+ <anchor id="system"/>
+
+ <blockquote>
+ <informalexample>
+ <programlisting>
+system <replaceable>expression</replaceable>
+ </programlisting>
+ </informalexample>
+ </blockquote>
+
+ <para>
+ <replaceable>expression</replaceable> specifies an external program
+ that
+ <command>maildrop</command> runs as a subprocess.
+ The subprocess's standard input gets connected to
+ <filename>/dev/null</filename>, and the subprocess inherits
+ the standard output and error from
+ <command>maildrop</command>.</para>
+ </refsect3>
+
+ <refsect3>
<title>to - deliver message to a mailbox</title>
<anchor id="to"/>
<blockquote>
diff --git a/maildrop/recipenode.C b/maildrop/recipenode.C
index c69c017..031eec0 100644
--- a/maildrop/recipenode.C
+++ b/maildrop/recipenode.C
@@ -496,7 +496,7 @@ RecipeNode *c;
debug += '\0';
r.errmsg(*this, debug);
}
-
+
long l=bb.Length();
if (n < 0 || n > l) n=l;
@@ -622,6 +622,17 @@ RecipeNode *c;
throw "Unable to filter message.";
b = "0";
break;
+ case system:
+ if (!firstChild)
+ throw "Internal error in system statement.";
+ firstChild->Evaluate(r,b);
+ b += '\0';
+ if (VerboseLevel() > 0)
+ merr << "maildrop: Executing system command " <<
+ (const char *)b << "\n";
+ executesystem(b);
+ b = "0";
+ break;
case exception:
if (!firstChild)
throw "Internal error in delivery statement.";
diff --git a/maildrop/recipenode.h b/maildrop/recipenode.h
index cff0a7a..4a76a42 100644
--- a/maildrop/recipenode.h
+++ b/maildrop/recipenode.h
@@ -97,6 +97,7 @@ public:
exception,
echo,
xfilter,
+ system,
dotlock,
flock,
logfile,
diff --git a/maildrop/recipeparse.C b/maildrop/recipeparse.C
index f43cc1b..6a83042 100644
--- a/maildrop/recipeparse.C
+++ b/maildrop/recipeparse.C
@@ -173,6 +173,14 @@ RecipeNode *n, *o;
throw "Syntax error.";
lex->token(cur_tok);
return (n);
+ case Token::tokensystem:
+ lex->token(cur_tok);
+ n=alloc(RecipeNode::system);
+ n->AppendSibling( ParseExpr());
+ if (cur_tok.Type() != Token::semicolon)
+ throw "Syntax error.";
+ lex->token(cur_tok);
+ return (n);
case Token::dotlock:
lex->token(cur_tok);
n=alloc(RecipeNode::dotlock);
diff --git a/maildrop/token.C b/maildrop/token.C
index c6ab42d..59ca3e0 100644
--- a/maildrop/token.C
+++ b/maildrop/token.C
@@ -50,6 +50,7 @@ static const char *names[]={
"exception",
"echo",
"xfilter",
+ "system",
"dotlock",
"flock",
"logfile",
diff --git a/maildrop/token.h b/maildrop/token.h
index 0a97471..f2829b1 100644
--- a/maildrop/token.h
+++ b/maildrop/token.h
@@ -65,6 +65,7 @@ public:
exception,
echo,
tokenxfilter,
+ tokensystem,
dotlock,
flock,
logfile,