Skip to content

Commit

Permalink
Add new plugin to call a Lua script.
Browse files Browse the repository at this point in the history
  • Loading branch information
bruceg committed Apr 7, 2011
1 parent 000294f commit 8350ee9
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 0 deletions.
1 change: 1 addition & 0 deletions INSTHIER
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ c:::755::plugin-check-fqdn.so
c:::755::plugin-clamav.so
c:::755::plugin-counters.so
c:::755::plugin-cvm-validate.so
c?:::755::plugin-lua.so
c:::755::plugin-mailrules.so
c:::755::plugin-patterns.so
c:::755::plugin-qmail-validate.so
Expand Down
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
-------------------------------------------------------------------------------
Changes in version 1.20

- Added Lua scripting plugin (optional, build with 'make lua').

- Modified the qmail backend to evaluate $QMAILQUEUE as late as possible.
This allows more options for changing $QMAILQUEUE in plugins.

Expand Down
2 changes: 2 additions & 0 deletions README.in
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ Requirements:

- bglibs version 1.101
- cvm version 0.82
- Lua version 5 or later (optional)

Installation:

- Build the sources by running "make".
- To build the Lua plugin, run "make lua".
- After the package has been compiled, run "make install" as root.

Configuration:
Expand Down
1 change: 1 addition & 0 deletions TOP.spac
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
: all lua clean clean-spac install
5 changes: 5 additions & 0 deletions libraries.spac
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dependon([ fn[:-2]+'.a' for fn in glob('*=l')
if fn[:3] <> 'lib'])
dependon([ fn[:-2]+'.la' for fn in glob('lib*=l')])
dependon([ fn[:-3]+'.so' for fn in glob('*=so')
if fn[:-3] != 'plugin-lua'])
1 change: 1 addition & 0 deletions lua.spac
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dependon(['plugin-lua.so'])
153 changes: 153 additions & 0 deletions plugin-lua.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "mailfront.h"
#include <msg/msg.h>

static lua_State* L = 0;

static const response* get_response(void)
{
static response resp;
static str msgcopy;
const char* msg;

resp.number = lua_tonumber(L, -2);
msg = lua_tostring(L, -1);
if (msg == 0 || *msg == 0) {
resp.message = (resp.number < 400) ? "OK"
: (resp.number < 500) ? "Deferred"
: "Rejected";
}
else {
if (!str_copys(&msgcopy, msg))
return &resp_oom;
resp.message = msgcopy.s;
}
lua_pop(L, 2);
return (resp.number > 0) ? &resp : 0;
}

static int setup(const char* name)
{
if (L != 0) {
lua_getfield(L, LUA_GLOBALSINDEX, name);
if (lua_isfunction(L, -1))
return 1;
lua_pop(L, 1);
}
return 0;
}

static const response* callit(int nparams)
{
int code;
if ((code = lua_pcall(L, nparams, 2, 0)) != 0) {
msgf("{Lua error: }d{ (}s{)}", code, lua_tostring(L, -1));
lua_pop(L, 1);
return &resp_internal;
}
return get_response();
}

static const response* init(void)
{
const char* env;

env = session_getenv("LUA_SCRIPT");
if (env != 0) {
L = luaL_newstate();
if (L == 0)
return &resp_oom;
switch (luaL_loadfile(L, env)) {
case LUA_ERRMEM:
return &resp_oom;
case 0:
break;
case LUA_ERRFILE:
msg3("Cannot read \"", env, "\"");
return &resp_internal;
case LUA_ERRSYNTAX:
msg3("Syntax error in \"", env, "\"");
return &resp_internal;
default:
return &resp_internal;
}
return callit(0);
}
return 0;
}

static const response* reset(void)
{
if (setup("reset"))
return callit(0);
return 0;
}

static const response* helo(str* hostname)
{
if (setup("helo")) {
lua_pushlstring(L, hostname->s, hostname->len);
return callit(1);
}
return 0;
}

static const response* sender(str* address)
{
if (setup("sender")) {
lua_pushlstring(L, address->s, address->len);
return callit(1);
}
return 0;
}

static const response* recipient(str* address)
{
if (setup("recipient")) {
lua_pushlstring(L, address->s, address->len);
return callit(1);
}
return 0;
}

static const response* data_start(int fd)
{
if (setup("data_start")) {
lua_pushinteger(L, fd);
return callit(1);
}
return 0;
}

static const response* data_block(const char* bytes, unsigned long len)
{
if (setup("data_block")) {
lua_pushlstring(L, bytes, len);
return callit(1);
}
return 0;
}

static const response* message_end(int fd)
{
if (setup("message_end")) {
lua_pushinteger(L, fd);
return callit(1);
}
return 0;
}

struct plugin plugin = {
.version = PLUGIN_VERSION,
.flags = 0,
.init = init,
.reset = reset,
.helo = helo,
.sender = sender,
.recipient = recipient,
.data_start = data_start,
.data_block = data_block,
.message_end = message_end,
};
32 changes: 32 additions & 0 deletions plugin-lua.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<html>
<body>

<h2><a href="mailfront.html">mailfront</a></h2>

<h1>Plugin: lua</h1>

<hr />

<p>This plugin allows for extending mailfront
using <a href="http://www.lua.org/">Lua</a>. All actions in
the <a href="plugin-api.html">mailfront plugin API</a> are exposed
through calls to functions of the same name in the script, with the
exception of the "<tt>init</tt>" function. For this function, the
return from the script itself is used. The functions are passed the
same parameters as described in the API. The return value from these
functions is a numeric SMTP response code followed by a message. If
the number is zero or <tt>nil</tt>, it is treated as an NULL response.
If the message is missing, the script wrapper provides a simple one
based on the response code.</p>

<h2>Configuration</h2>

<dl>

<dt><tt>$LUA_SCRIPT</tt></dt> <dd>The file name of the Lua script to
load. If not set, this plugin does nothing.</dd>

</dl>

</body>
</html>
3 changes: 3 additions & 0 deletions plugin-lua=so
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-lbg
-llua
-lbg-sysdeps
64 changes: 64 additions & 0 deletions tests/plugin-lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
export LUA_SCRIPT=script.lua
doit() {
cat > script.lua
echo
sfecho lua <<EOF
HELO helohost
MAIL FROM:<sender>
RCPT TO:<recip1>
RCPT TO:<recip2>
DATA
Header: one
.
EOF
}

doit <<EOF
return 555,"init failed"
EOF

doit <<EOF
function reset()
return 253,'reset'
end

function sender(a)
return 251,'Lua sender='..a
end

function recipient(a)
return 252,'Lua recip='..a
end

function data_start(fd)
return 354
end
EOF

doit <<EOF
function data_start(fd)
return 421,'start fd='..fd
end
EOF

rm -f $LUA_SCRIPT
unset LUA_SCRIPT

<result>

555 init failed^M

250 local.host^M
251 Lua sender=sender^M
252 Lua recip=recip1^M
252 Lua recip=recip2^M
354 End your message with a period on a line by itself.^M
250 Received 12 bytes.^M

250 local.host^M
250 Sender='sender'.^M
250 Recipient='recip1'.^M
250 Recipient='recip2'.^M
421 start fd=-1^M
500 5.5.1 Not implemented.^M
500 5.5.1 Not implemented.^M

0 comments on commit 8350ee9

Please sign in to comment.