diff options
Diffstat (limited to 'maildrop')
| -rw-r--r-- | maildrop/filter.C | 63 | ||||
| -rw-r--r-- | maildrop/funcs.h | 1 | ||||
| -rw-r--r-- | maildrop/lexer.C | 3 | ||||
| -rw-r--r-- | maildrop/maildrop.sgml | 13 | ||||
| -rw-r--r-- | maildrop/maildropfilter.sgml | 26 | ||||
| -rw-r--r-- | maildrop/recipenode.C | 13 | ||||
| -rw-r--r-- | maildrop/recipenode.h | 1 | ||||
| -rw-r--r-- | maildrop/recipeparse.C | 8 | ||||
| -rw-r--r-- | maildrop/token.C | 1 | ||||
| -rw-r--r-- | maildrop/token.h | 1 |
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, |
