From 4238d38f75d45793521a3b49ba421413d2b53a21 Mon Sep 17 00:00:00 2001 From: Sam Varshavchik Date: Sun, 23 Jul 2017 23:16:48 -0400 Subject: maildrop: add the "system" command. --- maildrop/filter.C | 63 +++++++++++++++++++++++++++++++++++++++++++- maildrop/funcs.h | 1 + maildrop/lexer.C | 3 +++ maildrop/maildrop.sgml | 13 +++++++-- maildrop/maildropfilter.sgml | 26 +++++++++++++++++- maildrop/recipenode.C | 13 ++++++++- maildrop/recipenode.h | 1 + maildrop/recipeparse.C | 8 ++++++ maildrop/token.C | 1 + 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 @@ -619,6 +619,13 @@ The log command is not allowed in embedded mode. The logfile command is not allowed in embedded mode. + + system + + +The system command is not allowed in embedded mode. + + to @@ -663,8 +670,10 @@ suspended for any additional filter files that are included from This allows the system administrator to have a controlled environment for -running external commands (via the backticks, or the -xfilter command). +running external commands (via the backticks, the +system +or the +xfilter commands). 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" RETURNCODEThis variable is set when maildrop - runs the xfilter command, or a command that's + runs the + system command, + xfilter command, or a command that's specified within a pair of backtick characters ( command substitution ). The RETURNCODE variable will be set to the exit code of the command, after it completes. @@ -1484,6 +1486,28 @@ log expression standard output. + + system - execute a system command + + +
+ + +system expression + + +
+ + + expression specifies an external program + that + maildrop runs as a subprocess. + The subprocess's standard input gets connected to + /dev/null, and the subprocess inherits + the standard output and error from + maildrop. +
+ to - deliver message to a mailbox 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, -- cgit v1.2.3