Skip to content

Commit 3e5d5a3

Browse files
Nicellaatxe
andauthored
Process: env (#130)
Builds upon #129 by adding `process.env`. It has a metatable that implements `__index`, `__newindex`, and `__iter` to act as a proxy for the process's environment. --------- Co-authored-by: ariel <aweiss@hey.com>
1 parent 6c5152e commit 3e5d5a3

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

examples/process_env.luau

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
local process = require("@lute/process")
2+
3+
print(process.env.HOME)
4+
print(process.env.LUTE_HOME)
5+
process.env.LUTE_HOME = "/home/lute"
6+
print(process.env.LUTE_HOME)
7+
8+
for k, v in process.env do
9+
print(k, v)
10+
end

process/src/process.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,137 @@ int create(lua_State* L)
371371
return lua_yield(L, 0);
372372
}
373373

374+
static int envIndex(lua_State* L)
375+
{
376+
const char* key = luaL_checkstring(L, 2);
377+
char value[1024];
378+
size_t size = sizeof(value);
379+
int err = uv_os_getenv(key, value, &size);
380+
381+
if (err == UV_ENOBUFS)
382+
{
383+
char* buffer = (char*)malloc(size);
384+
err = uv_os_getenv(key, buffer, &size);
385+
if (err == 0)
386+
{
387+
lua_pushlstring(L, buffer, size);
388+
free(buffer);
389+
return 1;
390+
}
391+
free(buffer);
392+
}
393+
else if (err == UV_ENOENT)
394+
{
395+
lua_pushnil(L);
396+
return 1;
397+
}
398+
else if (err != 0)
399+
{
400+
luaL_error(L, "Failed to get environment variable: %s", uv_strerror(err));
401+
return 0;
402+
}
403+
404+
lua_pushlstring(L, value, size);
405+
return 1;
406+
}
407+
408+
static int envNewindex(lua_State* L)
409+
{
410+
const char* key = luaL_checkstring(L, 2);
411+
int err;
412+
413+
if (lua_isnil(L, 3))
414+
{
415+
err = uv_os_unsetenv(key);
416+
}
417+
else
418+
{
419+
const char* value = luaL_checkstring(L, 3);
420+
err = uv_os_setenv(key, value);
421+
}
422+
423+
if (err != 0)
424+
{
425+
luaL_error(L, "Failed to set environment variable: %s", uv_strerror(err));
426+
}
427+
428+
return 0;
429+
}
430+
431+
struct EnvIter
432+
{
433+
uv_env_item_t* items;
434+
int count;
435+
int index;
436+
};
437+
438+
static int envIterNext(lua_State* L)
439+
{
440+
EnvIter* iter = (EnvIter*)lua_touserdata(L, lua_upvalueindex(1));
441+
442+
if (iter->index >= iter->count)
443+
{
444+
return 0;
445+
}
446+
447+
lua_pushstring(L, iter->items[iter->index].name);
448+
lua_pushstring(L, iter->items[iter->index].value);
449+
iter->index++;
450+
return 2;
451+
}
452+
453+
static int envIter(lua_State* L)
454+
{
455+
uv_env_item_t* items;
456+
int count;
457+
int err = uv_os_environ(&items, &count);
458+
459+
if (err != 0)
460+
{
461+
luaL_error(L, "Failed to get environment variables: %s", uv_strerror(err));
462+
return 0;
463+
}
464+
465+
EnvIter* iter = (EnvIter*)lua_newuserdata(L, sizeof(EnvIter));
466+
iter->items = items;
467+
iter->count = count;
468+
iter->index = 0;
469+
470+
luaL_getmetatable(L, "process.env.iterator");
471+
lua_setmetatable(L, -2);
472+
473+
lua_pushvalue(L, -1);
474+
lua_pushcclosure(L, envIterNext, "envIterNext", 1);
475+
476+
return 1;
477+
}
478+
479+
static int envIterGc(lua_State* L)
480+
{
481+
EnvIter* iter = (EnvIter*)lua_touserdata(L, 1);
482+
if (iter->items)
483+
{
484+
uv_os_free_environ(iter->items, iter->count);
485+
iter->items = nullptr;
486+
iter->count = 0;
487+
}
488+
return 0;
489+
}
490+
374491
} // namespace process
375492

493+
static const luaL_Reg processEnvMeta[] = {
494+
{"__index", process::envIndex},
495+
{"__newindex", process::envNewindex},
496+
{"__iter", process::envIter},
497+
{nullptr, nullptr}
498+
};
499+
500+
static const luaL_Reg processEnvIterMeta[] = {
501+
{"__gc", process::envIterGc},
502+
{nullptr, nullptr}
503+
};
504+
376505
int luaopen_process(lua_State* L)
377506
{
378507
luaL_register(L, "process", process::lib);
@@ -392,6 +521,16 @@ int luteopen_process(lua_State* L)
392521
lua_setfield(L, -2, name);
393522
}
394523

524+
luaL_newmetatable(L, "process.env.iterator");
525+
luaL_register(L, nullptr, processEnvIterMeta);
526+
lua_pop(L, 1);
527+
528+
lua_newtable(L);
529+
luaL_newmetatable(L, "process.env");
530+
luaL_register(L, nullptr, processEnvMeta);
531+
lua_setmetatable(L, -2);
532+
lua_setfield(L, -2, "env");
533+
395534
lua_setreadonly(L, -1, 1);
396535

397536
return 1;

0 commit comments

Comments
 (0)