/* * Copyright (C) 2016 "IoT.bzh" * Author Fulup Ar Foll * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ref: * http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call * http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/ */ #define _GNU_SOURCE #include #include #include #include "lua.h" #include "lauxlib.h" #include "lualib.h" #include "ctl-binding.h" #include "wrap-json.h" static lua_State* luaState; typedef enum { LUA_DOCALL, LUA_DOSTRING, LUA_DOSCRIPT, } LuaDoActionT; // List Avaliable Configuration Files PUBLIC json_object* ScanForConfig (char* searchPath, char *pre, char *ext) { json_object *responseJ; DIR *dirHandle; char *dirPath; char* dirList= strdup(searchPath); size_t extLen = strlen(ext); responseJ = json_object_new_array(); for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) { struct dirent *dirEnt; dirHandle = opendir (dirPath); if (!dirHandle) { AFB_NOTICE ("CONFIG-SCANNING dir=%s not readable", dirPath); continue; } AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", dirPath); while ((dirEnt = readdir(dirHandle)) != NULL) { // Unknown type is accepted to support dump filesystems if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) { // check prefix and extention size_t extIdx=strlen(dirEnt->d_name) - extLen; if (extIdx <= 0) continue; if (pre && !strcasestr (dirEnt->d_name, pre)) continue; if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue; struct json_object *pathJ = json_object_new_object(); json_object_object_add(pathJ, "dirpath", json_object_new_string(dirPath)); json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name)); json_object_array_add(responseJ, pathJ); } } } free (dirList); return (responseJ); } STATIC int LuaPrintNotice(lua_State* luaState) { int count = lua_gettop(luaState); for (int idx=1; idx <= count; ++idx) { const char *str = lua_tostring(luaState, idx); // Get string // Output string. AFB_NOTICE (str); } return 0; // no value return } STATIC int LuaPushArgument (json_object *arg) { switch (json_object_get_type(arg)) { case json_type_object: lua_newtable (luaState); json_object_object_foreach (arg, key, val) { int done = LuaPushArgument (val); if (done) { lua_pushstring(luaState, key); // table.key = val lua_settable(luaState, -3); } } break; case json_type_int: lua_pushinteger(luaState, json_object_get_int(arg)); break; case json_type_string: lua_pushstring(luaState, json_object_get_string(arg)); break; case json_type_boolean: lua_pushboolean(luaState, json_object_get_boolean(arg)); break; case json_type_double: lua_pushnumber(luaState, json_object_get_double(arg)); break; default: return 0; } return 1; } // Generated some fake event based on watchdog/counter PUBLIC void LuaDoAction (LuaDoActionT action, afb_req request) { int err, count=0; json_object* queryJ = afb_req_json(request); switch (action) { case LUA_DOSTRING: { const char *script = json_object_get_string(queryJ); err=luaL_loadstring(luaState, script); if (err) { AFB_ERROR ("LUA-DO-COMPILE:FAIL String=%s err=%s", script, lua_tostring(luaState,-1) ); goto OnErrorExit; } break; } case LUA_DOCALL: { const char *func; json_object *args; err= wrap_json_unpack (queryJ, "{s:s, s?o !}", "func", &func,"args", &args); if (err) { AFB_ERROR ("LUA-DOCALL-SYNTAX missing func|args args=%s", json_object_get_string(queryJ)); goto OnErrorExit; } // load function (should exist in CONTROL_PATH_LUA lua_getglobal(luaState, func); // push arguments on the stack if (json_object_get_type(args) != json_type_array) { count= LuaPushArgument (args); } else { for (int idx=0; idx