static int aux_close (lua_State *L) { lua_getfenv(L, 1); lua_getfield(L, -1, "__close"); return (lua_tocfunction(L, -1))(L); }
static int aux_getfenv (lua_State *L) { lua_getfenv(L, -1); lua_pushliteral(L, "__fenv"); lua_rawget(L, -2); return !lua_isnil(L, -1); }
/* Registers a callback, callback_index can't be negative */ void luv_register_event(lua_State* L, int userdata_index, const char* name, int callback_index) { lua_getfenv(L, userdata_index); lua_pushvalue(L, callback_index); lua_setfield(L, -2, name); lua_pop(L, 1); }
//! Get a field from the environment table of an object void luaT_getenvfield(lua_State *L, int index, const char *k) { lua_getfenv(L, index); lua_getfield(L, -1, k); lua_replace(L, -2); }
static void lua_getuservalue(lua_State *L, int idx) { lua_getfenv(L, idx); }
void LuaInterface::getEnv(int index) { assert(hasIndex(index)); lua_getfenv(L, index); }
static int db_getfenv (lua_State *L) { lua_getfenv(L, 1); return 1; }
static int db_getfenv (lua_State *L) { luaL_checkany(L, 1); lua_getfenv(L, 1); return 1; }
/* Class index function * If the object is a userdata (ie, an object), it searches the field in * the alternative table stored in the corresponding "ubox" table. */ static int class_index_event (lua_State* L) { int t = lua_type(L,1); if (t == LUA_TUSERDATA) { /* Access alternative table */ #ifdef LUA_VERSION_NUM /* new macro on version 5.1 */ lua_getfenv(L,1); if (!lua_rawequal(L, -1, TOLUA_NOPEER)) { lua_pushvalue(L, 2); /* key */ lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */ if (!lua_isnil(L, -1)) return 1; }; #else lua_pushstring(L,"tolua_peers"); lua_rawget(L,LUA_REGISTRYINDEX); /* stack: obj key ubox */ lua_pushvalue(L,1); lua_rawget(L,-2); /* stack: obj key ubox ubox[u] */ if (lua_istable(L,-1)) { lua_pushvalue(L,2); /* key */ lua_rawget(L,-2); /* stack: obj key ubox ubox[u] value */ if (!lua_isnil(L,-1)) return 1; } #endif lua_settop(L,2); /* stack: obj key */ /* Try metatables */ lua_pushvalue(L,1); /* stack: obj key obj */ while (lua_getmetatable(L,-1)) { /* stack: obj key obj mt */ lua_remove(L,-2); /* stack: obj key mt */ if (lua_isnumber(L,2)) /* check if key is a numeric value */ { /* try operator[] */ lua_pushstring(L,".geti"); lua_rawget(L,-2); /* stack: obj key mt func */ if (lua_isfunction(L,-1)) { lua_pushvalue(L,1); lua_pushvalue(L,2); lua_call(L,2,1); return 1; } } else { lua_pushvalue(L,2); /* stack: obj key mt key */ lua_rawget(L,-2); /* stack: obj key mt value */ if (!lua_isnil(L,-1)) return 1; else lua_pop(L,1); /* try C/C++ variable */ lua_pushstring(L,".get"); lua_rawget(L,-2); /* stack: obj key mt tget */ if (lua_istable(L,-1)) { lua_pushvalue(L,2); lua_rawget(L,-2); /* stack: obj key mt value */ if (lua_iscfunction(L,-1)) { lua_pushvalue(L,1); lua_pushvalue(L,2); lua_call(L,2,1); return 1; } else if (lua_istable(L,-1)) { /* deal with array: create table to be returned and cache it in ubox */ void* u = *((void**)lua_touserdata(L,1)); lua_newtable(L); /* stack: obj key mt value table */ lua_pushstring(L,".self"); lua_pushlightuserdata(L,u); lua_rawset(L,-3); /* store usertype in ".self" */ lua_insert(L,-2); /* stack: obj key mt table value */ lua_setmetatable(L,-2); /* set stored value as metatable */ lua_pushvalue(L,-1); /* stack: obj key met table table */ lua_pushvalue(L,2); /* stack: obj key mt table table key */ lua_insert(L,-2); /* stack: obj key mt table key table */ storeatubox(L,1); /* stack: obj key mt table */ return 1; } } } lua_settop(L,3); } lua_pushnil(L); return 1; } else if (t== LUA_TTABLE) { module_index_event(L); return 1; } lua_pushnil(L); return 1; }
/* * Arguments: dpool_udata, [timeout (milliseconds)] * Returns: data_items (any) ... */ static int dpool_get (lua_State *L) { struct sys_thread *td = sys_thread_get(); struct data_pool *dp = checkudata(L, 1, DPOOL_TYPENAME); const msec_t timeout = lua_isnoneornil(L, 2) ? TIMEOUT_INFINITE : (msec_t) lua_tointeger(L, 2); int nput; if (!td) luaL_argerror(L, 0, "Threading not initialized"); lua_settop(L, 1); lua_getfenv(L, 1); /* storage */ lua_insert(L, 1); if ((dp->flags & DPOOL_GETONEMPTY) && !dp->n) { lua_rawgetp(L, 1, (void *) DPOOL_GETONEMPTY); lua_insert(L, 2); lua_call(L, 1, LUA_MULTRET); nput = lua_gettop(L) - 1; if (nput) return nput; } for (; ; ) { /* get from storage */ if (dp->n) { const int idx = dp->idx + 1; int i; lua_rawgeti(L, 1, idx); nput = lua_tointeger(L, -1); lua_pushnil(L); lua_rawseti(L, 1, idx); dp->idx = idx + nput; for (i = dp->idx; i > idx; --i) { lua_rawgeti(L, 1, i); lua_pushnil(L); lua_rawseti(L, 1, i); } if (dp->idx == dp->top) dp->idx = dp->top = 0; if (dp->n-- == dp->max) { thread_event_signal(&dp->tev); } return nput; } /* wait signal */ { int res; dp->nwaits++; res = thread_event_wait(&dp->tev, td, timeout); dp->nwaits--; sys_thread_check(td); if (res) { if (res == 1) { lua_pushboolean(L, 0); return 1; /* timed out */ } return sys_seterror(L, 0); } } /* get directly from another thread */ nput = dp->nput; if (nput) { dp->nput = 0; luaL_checkstack(L, nput, NULL); lua_xmove(dp->td->L, L, nput); return nput; } } }
/** * walk through the content array * * content = { "<pre>", { file = "/content" } , "</pre>" } * * header["Content-Type"] = "text/html" * * return 200 */ static int magnet_attach_content(server * srv, connection * con, plugin_data * p, lua_State * L) { UNUSED(p); /** * get the environment of the function */ assert(lua_isfunction(L, -1)); lua_getfenv(L, -1); /* -1 is the function */ lua_getfield(L, -1, "lighty"); /* lighty.* from the env */ assert(lua_istable(L, -1)); lua_getfield(L, -1, "content"); /* lighty.content */ if (lua_istable(L, -1)) { int i; /* * header is found, and is a table */ for (i = 1;; i++) { lua_rawgeti(L, -1, i); /* * -1 is the value and should be the value ... aka a table */ if (lua_isstring(L, -1)) { size_t s_len = 0; const char *s = lua_tolstring(L, -1, &s_len); chunkqueue_append_mem(con->write_queue, s, s_len + 1); } else if (lua_istable(L, -1)) { lua_getfield(L, -1, "filename"); lua_getfield(L, -2, "length"); lua_getfield(L, -3, "offset"); if (lua_isstring(L, -3)) { /* filename has to be a string */ buffer *fn = buffer_init(); stat_cache_entry *sce; buffer_copy_string(fn, lua_tostring(L, -3)); if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, fn, &sce)) { off_t off = 0; off_t len = 0; if (lua_isnumber(L, -1)) { off = lua_tonumber(L, -1); } if (lua_isnumber(L, -2)) { len = lua_tonumber(L, -2); } else { len = sce->st.st_size; } if (off < 0) { return luaL_error(L, "offset for '%s' is negative", fn->ptr); } if (len < off) { return luaL_error(L, "offset > length for '%s'", fn->ptr); } chunkqueue_append_file(con->write_queue, fn, off, len - off); } buffer_free(fn); } else { lua_pop(L, 3 + 2); /* correct the stack */ return luaL_error(L, "content[%d] is a table and requires the field \"filename\"", i); } lua_pop(L, 3); } else if (lua_isnil(L, -1)) { /* * oops, end of list */ lua_pop(L, 1); break; } else { lua_pop(L, 4); return luaL_error(L, "content[%d] is neither a string nor a table: ", i); } lua_pop(L, 1); /* pop the content[...] table */ } } else { return luaL_error(L, "lighty.content has to be a table"); } lua_pop(L, 1); /* pop the header-table */ lua_pop(L, 1); /* pop the lighty-table */ lua_pop(L, 1); /* php the function env */ return 0; }
int main(int argc, const char **argv) { bind_port = default_port; char *cwd = init_process_title(argc, argv); char *msg = NULL; update_time(); if(getarg("cache-size")) { msg = getarg("cache-size"); YAC_CACHE_SIZE = atoi(msg); if(msg[strlen(msg) - 1] == 'm') { YAC_CACHE_SIZE = YAC_CACHE_SIZE * 1024 * 1024; } else if(msg[strlen(msg) - 1] == 'k') { YAC_CACHE_SIZE = YAC_CACHE_SIZE * 1024; } } if(YAC_CACHE_SIZE < 1024 * 1024 * 2) { YAC_CACHE_SIZE = 1024 * 1024 * 2; } if(!yac_storage_startup(YAC_CACHE_SIZE / 16, YAC_CACHE_SIZE - (YAC_CACHE_SIZE / 16), &msg)) { LOGF(ERR, "Shared memory allocator startup failed at '%s': %s", msg, strerror(errno)); exit(1); } lua_State *L = luaL_newstate(); if(!L) { LOGF(ERR, "error for luaL_newstate"); exit(1); } luaL_openlibs(L); lua_getglobal(L, "_VERSION"); const char *lua_ver = lua_tostring(L, -1); lua_getglobal(L, "jit"); if(lua_istable(L, -1)) { lua_getfield(L, -1, "version"); if(lua_isstring(L, -1)) { lua_ver = lua_tostring(L, -1); } } sprintf(hostname, "%s", lua_ver); lua_close(L); _L = luaL_newstate(); lua_gc(_L, LUA_GCSTOP, 0); luaL_openlibs(_L); /* Load Lua libraries */ lua_gc(_L, LUA_GCRESTART, 0); if(getarg("host-route")) { lua_pushstring(_L, getarg("host-route")); lua_setglobal(_L, "HOST_ROUTE"); } if(!update_vhost_routes(getarg("host-route")) && !getarg("app")) { LOGF(WARN, "no host-route or app arguments! using defalut settings."); sprintf(tbuf_4096, "%s/host-route.lua", process_chdir); update_vhost_routes(tbuf_4096); } if(getarg("code-cache-ttl")) { /// default = 60s lua_pushnumber(_L, atoi(getarg("code-cache-ttl"))); lua_setglobal(_L, "CODE_CACHE_TTL"); } else { lua_pushnumber(_L, code_cache_ttl); lua_setglobal(_L, "CODE_CACHE_TTL"); } lua_getglobal(_L, "require"); lua_pushcfunction(_L, lua_f_package_require); lua_getfenv(_L, -2); int ret = lua_setfenv(_L, -2); lua_setglobal(_L, "require"); lua_pop(_L, 1); lua_register(_L, "echo", lua_echo); lua_register(_L, "print_error", lua_print_error); lua_register(_L, "sendfile", lua_sendfile); lua_register(_L, "header", lua_header); lua_register(_L, "clear_header", lua_clear_header); lua_register(_L, "__end", lua_end); lua_register(_L, "die", lua_die); lua_register(_L, "flush", lua_flush); lua_register(_L, "read_request_body", lua_read_request_body); lua_register(_L, "get_boundary", lua_f_get_boundary); lua_register(_L, "check_timeout", lua_check_timeout); lua_register(_L, "is_websocket", lua_f_is_websocket); lua_register(_L, "upgrade_to_websocket", lua_f_upgrade_to_websocket); lua_register(_L, "websocket_send", lua_f_websocket_send); lua_register(_L, "check_websocket_close", lua_f_check_websocket_close); lua_register(_L, "router", lua_f_router); lua_register(_L, "random_string", lua_f_random_string); lua_register(_L, "file_exists", lua_f_file_exists); lua_register(_L, "readfile", lua_f_readfile); lua_register(_L, "filemtime", lua_f_filemtime); lua_register(_L, "cache_set", lua_f_cache_set); lua_register(_L, "cache_get", lua_f_cache_get); lua_register(_L, "cache_del", lua_f_cache_del); luaopen_fastlz(_L); luaopen_coevent(_L); luaopen_libfs(_L); luaopen_string_utils(_L); luaopen_i18n(_L); luaopen_crypto(_L); lua_pop(_L, 1); sprintf(tbuf_4096, "package.path = '%slua-libs/?.lua;' .. package.path package.cpath = '%slua-libs/?.so;' .. package.cpath", cwd, cwd); luaL_dostring(_L, tbuf_4096); luaL_dostring(_L, "" "if not CODE_CACHE_TTL then CODE_CACHE_TTL = 60 end " \ "startloop = nil __CodeCache = {{},{}} __CodeCacheC = {false,false} " ); if(getarg("accesslog")) { ACCESS_LOG = open_log(getarg("accesslog"), 40960); if(!ACCESS_LOG) { LOGF(ERR, "Couldn't open access log file: %s", getarg("accesslog")); } } if(getarg("ssl-bind") && getarg("ssl-cert") && getarg("ssl-key")) { ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if(!ssl_ctx) { LOGF(ERR, "SSL_CTX_new Failed"); exit(1); } if(SSL_CTX_use_certificate_file(ssl_ctx, getarg("ssl-cert"), SSL_FILETYPE_PEM) != 1) { SSL_CTX_free(ssl_ctx); LOGF(ERR, "SSL_CTX_use_certificate_file"); exit(1); } if(SSL_CTX_use_PrivateKey_file(ssl_ctx, getarg("ssl-key"), SSL_FILETYPE_PEM) != 1) { SSL_CTX_free(ssl_ctx); LOGF(ERR, "SSL_CTX_use_PrivateKey_file"); exit(1); } SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL); if(getarg("ssl-ca")) { ssl_epd_idx = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); if(ssl_epd_idx == -1) { LOGF(ERR, "SSL_get_ex_new_index Failed"); exit(1); } if(SSL_CTX_load_verify_locations(ssl_ctx, getarg("ssl-ca"), NULL) != 1) { SSL_CTX_free(ssl_ctx); LOGF(ERR, "SSL_CTX_load_verify_locations"); exit(1); } else { SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); SSL_CTX_set_verify_depth(ssl_ctx, 4); } } } _shm_serv_status = shm_malloc(sizeof(serv_status_t)); bzero(_shm_serv_status->p, sizeof(serv_status_t)); attach_on_exit(on_master_exit_handler); return merry_start(argc, argv, help, master_main, on_master_exit_handler, worker_main, 0); }
static int l_str_reload_actual(lua_State *L) { // Reload a single string proxy // Stack: reload_cache proxy_to_reload <top // Mark string as reloaded lua_pushvalue(L, 2); lua_pushvalue(L, 2); lua_settable(L, 1); // Pull instructions out of the environment and remake value lua_getfenv(L, 2); bool bIsIndexOperation = false; int iCount = (int)lua_objlen(L, 3); aux_push_weak_table(L, 0); lua_pushvalue(L, 2); if(iCount != 0) { // Fetch reconstruction information, reloading any de-proxying any // string proxies which we come across. Also replace any references // to the root with the new root. lua_checkstack(L, iCount + 1); for(int i = 1; i <= iCount; ++i) { lua_rawgeti(L, 3, i); if(lua_type(L, -1) == LUA_TUSERDATA) { if(i == 1) bIsIndexOperation = true; lua_gettable(L, 1); // reload / change root lua_pushvalue(L, -1); lua_rawseti(L, 3, i); lua_rawget(L, 4); // de-proxy } } if(iCount == 2 && bIsIndexOperation) { // If there were two values, and the first was a proxy, then the // instruction is to perform a table lookup. lua_gettable(L, -2); lua_replace(L, -2); } else { // Otherwise, the first value was a method or method name. if(lua_type(L, 6) != LUA_TFUNCTION) { lua_pushvalue(L, 6); lua_gettable(L, 7); lua_replace(L, 6); } lua_call(L, iCount - 1, 1); } } else { // Root object lua_settop(L, 2); return 1; } // Update value lua_rawset(L, -3); lua_pop(L, 2); return 1; }
// __depersist metamethod handler static int l_str_depersist(lua_State *L) { lua_settop(L, 2); lua_insert(L, 1); LuaPersistReader *pReader = (LuaPersistReader*)lua_touserdata(L, 1); // Read the instructions for re-creating the value if(!pReader->readStackObject()) return 0; if(lua_type(L, 3) == LUA_TBOOLEAN && lua_toboolean(L, 3) == 1) { // The current code uses a boolean marker to indicate that the // instructions were stored in the environment. Replace the marker // with them. lua_getfenv(L, 2); lua_replace(L, 3); } else { // Older versions of the code wrote the instructions here, or nil for // no instructions. Convert nil to the empty table, and store the // instructions as the userdata's environment. if(lua_type(L, 3) == LUA_TNIL) { lua_newtable(L); lua_replace(L, 3); } lua_pushvalue(L, 3); lua_setfenv(L, 2); } // Prepare t, k for saving the value aux_push_weak_table(L, 0); lua_pushvalue(L, 2); if(lua_objlen(L, 3) == 0) { // No instructions provided, so read the value itself if(!pReader->readStackObject()) return 0; } else { // The instructions are a table of values; unpack them and replace // proxies with their values. bool bIsIndexOperation = false; int iCount = (int)lua_objlen(L, 3); lua_checkstack(L, iCount + 1); for(int i = 1; i <= iCount; ++i) { lua_rawgeti(L, 3, i); if(lua_type(L, -1) == LUA_TUSERDATA) { if(i == 1) bIsIndexOperation = true; lua_rawget(L, 4); } } if(iCount == 2 && bIsIndexOperation) { // If there were two values, and the first was a proxy, then the // instruction is to perform a table lookup. lua_gettable(L, -2); lua_replace(L, -2); } else { // Otherwise, the first value was a method or method name. if(lua_type(L, 6) != LUA_TFUNCTION) { lua_pushvalue(L, 6); lua_gettable(L, 7); lua_replace(L, 6); } lua_call(L, iCount - 1, 1); } } // Save the value lua_rawset(L, 4); return 0; }