-
Notifications
You must be signed in to change notification settings - Fork 1
/
lenviron.c
167 lines (135 loc) · 3.09 KB
/
lenviron.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
* Callisto - standalone scripting platform for Lua 5.4
* Copyright (c) 2023-2024 Jeremy Baxter.
*/
/***
* Getting and setting environment variables.
* @module environ
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <lua/lauxlib.h>
#include <lua/lua.h>
#include "callisto.h"
#include "util.h"
extern char **environ;
/***
* Table enabling easy access to environment
* variables.
*
* Has metamethods *\_\_index* and *\_\_newindex*,
* which allow for the table to be indexed with a
* string to get values of environment variables,
* or for fields to be set to set an environment
* variable.
*
* @table environ
* @usage
-- Print the value of an environment variable:
print(environ["MYVAR"])
-- Set an environment variable:
environ["MYVAR"] = 1
*/
/*
* Returns the value of the given environment variable.
*/
static int
environ__index(lua_State *L)
{
const char *variable; /* parameter 2 (string) */
char *ret;
variable = luaL_checkstring(L, 2);
ret = getenv(variable);
if (ret == NULL) /* no environment variable? */
lua_pushnil(L);
else
lua_pushstring(L, ret); /* push variable value */
return 1;
}
/*
* Sets the value of the given environment variable.
*/
static int
environ__newindex(lua_State *L)
{
int ret;
const char *variable; /* parameter 2 (string) */
const char *value; /* parameter 3 (string) */
variable = luaL_checkstring(L, 2);
if (lua_isnil(L, 3)) {
ret = unsetenv(variable); /* remove variable from environ */
if (ret == 0) /* did unsetenv succeed? */
return 0;
/* if unsetenv didn't succeed:
* (unsetenv only sets errno to EINVAL on error) */
return luaL_error(L, "invalid input string");
}
value = luaL_checkstring(L, 3);
ret = setenv(variable, value, 1);
if (ret == 0) /* did setenv succeed? */
return 0;
switch (errno) {
case EINVAL:
return luaL_error(L, "invalid input string");
break;
case ENOMEM:
return luaL_error(L, "insufficient memory");
break;
}
return 0;
}
static int
pairs_iter(lua_State *L)
{
char *line, *name;
size_t *envi, len;
int i;
len = 0;
envi = (size_t *)lua_touserdata(L, 1);
line = environ[*envi];
if (line == NULL) {
lua_pushnil(L);
return 1;
}
name = calloc(strlen(line), sizeof(char));
/* extract the name portion from the environ line */
for (i = 0; line[i] != '='; i++) {
if (line[i] == '\0')
return lfailm(L, "process environment is corrupted");
name[len] = line[i];
len++;
}
(*envi)++;
lua_pushlstring(L, name, len);
return 1;
}
static int
environ__pairs(lua_State *L)
{
size_t *p;
lua_pushcfunction(L, pairs_iter);
p = lua_newuserdatauv(L, sizeof(size_t), 0);
*p = 0;
return 2;
}
/* clang-format off */
static const luaL_Reg mt[] = {
{"__index", environ__index},
{"__newindex", environ__newindex},
{"__pairs", environ__pairs},
{NULL, NULL}
};
int
luaopen_environ(lua_State *L)
{
const luaL_Reg *lib;
lua_newtable(L);
luaL_newmetatable(L, CALLISTO_ENVIRON); /* metatable for environ */
for (lib = mt; lib->func; lib++) {
lua_pushcfunction(L, lib->func);
lua_setfield(L, -2, lib->name);
}
lua_setmetatable(L, -2);
return 1;
}