@@ -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+
376505int 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