Add lua code execution and asset storage from redbean command line

This commit is contained in:
Paul Kulchenko 2021-11-15 17:35:17 -08:00
parent 1526116192
commit 1de42b6293
2 changed files with 36 additions and 9 deletions

View file

@ -34,6 +34,7 @@ FLAGS
-b log message bodies -b log message bodies
-a log resource usage -a log resource usage
-g log handler latency -g log handler latency
-e run specified Lua command
-j enable ssl client verify -j enable ssl client verify
-k disable ssl fetch verify -k disable ssl fetch verify
-f log worker function calls -f log worker function calls
@ -47,6 +48,7 @@ FLAGS
-R /X=/Y rewrites X to Y [repeatable] -R /X=/Y rewrites X to Y [repeatable]
-K PATH tls private key path [repeatable] -K PATH tls private key path [repeatable]
-C PATH tls certificate(s) path [repeatable] -C PATH tls certificate(s) path [repeatable]
-A PATH add asset with path [repeatable]
-M INT tunes max message payload size [def. 65536] -M INT tunes max message payload size [def. 65536]
-t INT timeout ms or keepalive sec if <0 [def. 60000] -t INT timeout ms or keepalive sec if <0 [def. 60000]
-p PORT listen port [def. 8080; repeatable] -p PORT listen port [def. 8080; repeatable]
@ -743,7 +745,7 @@ FUNCTIONS
flag was used. If slurping large file into memory is a concern, flag was used. If slurping large file into memory is a concern,
then consider using ServeAsset which can serve directly off disk. then consider using ServeAsset which can serve directly off disk.
StoreAsset(path:str,data:str,mode:int) StoreAsset(path:str,data:str[,mode:int])
Stores asset to executable's ZIP central directory. This currently Stores asset to executable's ZIP central directory. This currently
happens in an append-only fashion and is still largely in the happens in an append-only fashion and is still largely in the
proof-of-concept stages. Currently only supported on Linux, XNU, proof-of-concept stages. Currently only supported on Linux, XNU,

View file

@ -1034,6 +1034,17 @@ static void LogLuaError(char *hook, char *err) {
ERRORF("(lua) failed to run %s: %s", hook, err); ERRORF("(lua) failed to run %s: %s", hook, err);
} }
static bool LuaRunCode(const char *code) {
lua_State *L = GL;
int status = luaL_loadstring(L, code);
if (status != LUA_OK || LuaCallWithTrace(L, 0, 0) != LUA_OK) {
LogLuaError("lua code", lua_tostring(L, -1));
lua_pop(L, 1);
return false;
}
return true;
}
static bool LuaOnClientConnection(void) { static bool LuaOnClientConnection(void) {
bool dropit; bool dropit;
uint32_t ip, serverip; uint32_t ip, serverip;
@ -2119,9 +2130,10 @@ static wontreturn void PrintUsage(FILE *f, int rc) {
static void GetOpts(int argc, char *argv[]) { static void GetOpts(int argc, char *argv[]) {
int opt; int opt;
bool storeasset = false;
while ((opt = getopt(argc, argv, while ((opt = getopt(argc, argv,
"jkazhdugvVsmbfB" "jkazhdugvVsmbfB"
"l:p:r:R:H:c:L:P:U:G:D:t:M:C:K:F:T:")) != -1) { "e:A:l:p:r:R:H:c:L:P:U:G:D:t:M:C:K:F:T:")) != -1) {
switch (opt) { switch (opt) {
CASE('v', ++__log_level); CASE('v', ++__log_level);
CASE('s', --__log_level); CASE('s', --__log_level);
@ -2137,6 +2149,10 @@ static void GetOpts(int argc, char *argv[]) {
CASE('m', logmessages = true); CASE('m', logmessages = true);
CASE('k', sslfetchverify = false); CASE('k', sslfetchverify = false);
CASE('j', sslclientverify = true); CASE('j', sslclientverify = true);
CASE('e', LuaRunCode(optarg));
CASE('A', storeasset = true;
LuaRunCode(gc(xasprintf("StoreAsset(%`'s, Slurp(%`'s))",
optarg, optarg))));
CASE('l', ProgramAddr(optarg)); CASE('l', ProgramAddr(optarg));
CASE('H', ProgramHeader(optarg)); CASE('H', ProgramHeader(optarg));
CASE('L', ProgramLogPath(optarg)); CASE('L', ProgramLogPath(optarg));
@ -2160,6 +2176,8 @@ static void GetOpts(int argc, char *argv[]) {
PrintUsage(stderr, EX_USAGE); PrintUsage(stderr, EX_USAGE);
} }
} }
// if storing asset(s) is requested, don't need to continue
if (storeasset) exit(0);
} }
static void AppendLogo(void) { static void AppendLogo(void) {
@ -5485,7 +5503,7 @@ static int LuaRe(lua_State *L) {
return 1; return 1;
} }
static bool LuaRun(const char *path, bool mandatory) { static bool LuaRunAsset(const char *path, bool mandatory) {
struct Asset *a; struct Asset *a;
const char *code; const char *code;
size_t pathlen, codelen; size_t pathlen, codelen;
@ -5496,7 +5514,7 @@ static bool LuaRun(const char *path, bool mandatory) {
lua_State *L = GL; lua_State *L = GL;
effectivepath.p = path; effectivepath.p = path;
effectivepath.n = pathlen; effectivepath.n = pathlen;
DEBUGF("(lua) LuaRun(%`'s)", path); DEBUGF("(lua) LuaRunAsset(%`'s)", path);
status = status =
luaL_loadbuffer(L, code, codelen, FreeLater(xasprintf("@%s", path))); luaL_loadbuffer(L, code, codelen, FreeLater(xasprintf("@%s", path)));
if (status != LUA_OK || LuaCallWithTrace(L, 0, 0) != LUA_OK) { if (status != LUA_OK || LuaCallWithTrace(L, 0, 0) != LUA_OK) {
@ -5694,7 +5712,7 @@ static char *GetDefaultLuaPath(void) {
return s; return s;
} }
static void LuaInit(void) { static void LuaStart(void) {
#ifndef STATIC #ifndef STATIC
size_t i; size_t i;
lua_State *L = GL = luaL_newstate(); lua_State *L = GL = luaL_newstate();
@ -5708,14 +5726,20 @@ static void LuaInit(void) {
lua_pushcfunction(L, kLuaFuncs[i].func); lua_pushcfunction(L, kLuaFuncs[i].func);
lua_setglobal(L, kLuaFuncs[i].name); lua_setglobal(L, kLuaFuncs[i].name);
} }
LuaSetArgv(L);
LuaSetConstant(L, "kLogDebug", kLogDebug); LuaSetConstant(L, "kLogDebug", kLogDebug);
LuaSetConstant(L, "kLogVerbose", kLogVerbose); LuaSetConstant(L, "kLogVerbose", kLogVerbose);
LuaSetConstant(L, "kLogInfo", kLogInfo); LuaSetConstant(L, "kLogInfo", kLogInfo);
LuaSetConstant(L, "kLogWarn", kLogWarn); LuaSetConstant(L, "kLogWarn", kLogWarn);
LuaSetConstant(L, "kLogError", kLogError); LuaSetConstant(L, "kLogError", kLogError);
LuaSetConstant(L, "kLogFatal", kLogFatal); LuaSetConstant(L, "kLogFatal", kLogFatal);
if (LuaRun("/.init.lua", true)) { #endif
}
static void LuaInit(void) {
#ifndef STATIC
lua_State *L = GL;
LuaSetArgv(L);
if (LuaRunAsset("/.init.lua", true)) {
hasonhttprequest = IsHookDefined("OnHttpRequest"); hasonhttprequest = IsHookDefined("OnHttpRequest");
hasonclientconnection = IsHookDefined("OnClientConnection"); hasonclientconnection = IsHookDefined("OnClientConnection");
hasonprocesscreate = IsHookDefined("OnProcessCreate"); hasonprocesscreate = IsHookDefined("OnProcessCreate");
@ -5730,7 +5754,7 @@ static void LuaInit(void) {
static void LuaReload(void) { static void LuaReload(void) {
#ifndef STATIC #ifndef STATIC
if (!LuaRun("/.reload.lua", false)) { if (!LuaRunAsset("/.reload.lua", false)) {
DEBUGF("(srvr) no /.reload.lua defined"); DEBUGF("(srvr) no /.reload.lua defined");
} }
#endif #endif
@ -5935,7 +5959,7 @@ static void HandleHeartbeat(void) {
Reindex(); Reindex();
getrusage(RUSAGE_SELF, &shared->server); getrusage(RUSAGE_SELF, &shared->server);
#ifndef STATIC #ifndef STATIC
LuaRun("/.heartbeat.lua", false); LuaRunAsset("/.heartbeat.lua", false);
CollectGarbage(); CollectGarbage();
#endif #endif
for (i = 0; i < servers.n; ++i) { for (i = 0; i < servers.n; ++i) {
@ -7036,6 +7060,7 @@ void RedBean(int argc, char *argv[]) {
OpenZip(true); OpenZip(true);
RestoreApe(); RestoreApe();
SetDefaults(); SetDefaults();
LuaStart();
GetOpts(argc, argv); GetOpts(argc, argv);
LuaInit(); LuaInit();
oldloglevel = __log_level; oldloglevel = __log_level;