9
9
#include <stdio.h>
10
10
#include <string.h>
11
11
12
+ #if MII_ENABLE_LUA
13
+ #include <lua.h>
14
+ #include <lualib.h>
15
+ #include <lauxlib.h>
16
+
17
+ /* After Lua 5.1, lua_objlen changed name and LUA_OK is defined */
18
+ #if LUA_VERSION_NUM <= 501
19
+ #define mii_lua_len lua_objlen
20
+ #define LUA_OK 0
21
+ #else
22
+ #define mii_lua_len lua_rawlen
23
+ #endif
24
+
25
+ #endif // MII_ENABLE_LUA
26
+
12
27
#include <dirent.h>
13
28
#include <errno.h>
14
29
#include <regex.h>
15
30
#include <unistd.h>
16
31
#include <sys/stat.h>
17
32
#include <wordexp.h>
18
33
34
+ #if !MII_ENABLE_LUA
19
35
static const char * _mii_analysis_lmod_regex_src =
20
36
"\\s*(prepend_path|append_path)\\s*\\(\\s*"
21
37
"\"PATH\"\\s*,\\s*\"([^\"]+)\"" ;
22
38
23
39
static regex_t _mii_analysis_lmod_regex ;
40
+ #else
41
+ /* Lua interpreter state */
42
+ static lua_State * lua_state ;
43
+
44
+ /* run lua module code in a sandbox */
45
+ int _mii_analysis_lua_run (lua_State * lua_state , const char * code , char * * * paths_out , int * num_paths_out );
46
+ #endif
24
47
25
48
/* word expansion functions */
26
49
char * _mii_analysis_expand (const char * expr );
@@ -32,6 +55,7 @@ int _mii_analysis_tcl(const char* path, char*** bins_out, int* num_bins_out);
32
55
/* path scanning functions */
33
56
int _mii_analysis_scan_path (char * path , char * * * bins_out , int * num_bins_out );
34
57
58
+ #if !MII_ENABLE_LUA
35
59
/*
36
60
* compile regexes
37
61
*/
@@ -43,12 +67,49 @@ int mii_analysis_init() {
43
67
44
68
return 0 ;
45
69
}
70
+ #else
71
+ /*
72
+ * initialize Lua interpreter
73
+ */
74
+ int mii_analysis_init () {
75
+ lua_state = luaL_newstate ();
76
+ luaL_openlibs (lua_state );
77
+
78
+ /* sandbox path when mii is installed */
79
+ char * lua_path = mii_join_path (MII_PREFIX , "share/mii/lua/sandbox.luac" );
80
+
81
+ if (access (lua_path , F_OK ) == 0 ) {
82
+ /* found file, try to execute it and return */
83
+ if (luaL_dofile (lua_state , lua_path ) == LUA_OK ) {
84
+ free (lua_path );
85
+ return 0 ;
86
+ }
87
+ }
88
+ free (lua_path );
89
+
90
+ lua_path = "./sandbox.luac" ;
91
+ if (access (lua_path , F_OK ) == 0 ) {
92
+ /* mii is not installed, but should work anyway */
93
+ if (luaL_dofile (lua_state , lua_path ) == LUA_OK )
94
+ return 0 ;
95
+ }
96
+
97
+ mii_error ("failed to load Lua file" );
98
+ lua_close (lua_state );
99
+
100
+ return -1 ;
101
+ }
102
+ #endif
46
103
47
104
/*
48
- * clean up regexes
105
+ * cleanup regexes or Lua interpreter
49
106
*/
50
107
void mii_analysis_free () {
108
+ #if !MII_ENABLE_LUA
51
109
regfree (& _mii_analysis_lmod_regex );
110
+ #else
111
+ lua_close (lua_state );
112
+ #endif
52
113
}
53
114
54
115
/*
@@ -65,20 +126,57 @@ int mii_analysis_run(const char* modfile, int modtype, char*** bins_out, int* nu
65
126
return 0 ;
66
127
}
67
128
129
+ #if MII_ENABLE_LUA
130
+ /*
131
+ * run a modulefile's code in a Lua sandbox
132
+ */
133
+ int _mii_analysis_lua_run (lua_State * lua_state , const char * code , char * * * paths_out , int * num_paths_out ) {
134
+ /* execute modulefile */
135
+ int res ;
136
+ lua_getglobal (lua_state , "sandbox_run" );
137
+ lua_pushstring (lua_state , code );
138
+ res = lua_pcall (lua_state , 1 , 1 , 0 );
139
+
140
+ if (res != LUA_OK ) {
141
+ mii_error ("Error occured in Lua sandbox : %s" , lua_tostring (lua_state , -1 ));
142
+ lua_pop (lua_state , 1 );
143
+ return -1 ;
144
+ }
145
+
146
+ luaL_checktype (lua_state , 1 , LUA_TTABLE );
147
+
148
+ /* allocate memory for the paths */
149
+ * num_paths_out = mii_lua_len (lua_state , -1 );
150
+ * paths_out = malloc (* num_paths_out * sizeof (char * ));
151
+
152
+ /* retrieve paths from Lua stack */
153
+ for (int i = 1 ; i <= * num_paths_out ; ++ i ) {
154
+ lua_rawgeti (lua_state , - i , i );
155
+ (* paths_out )[i - 1 ] = mii_strdup (lua_tostring (lua_state , -1 ));
156
+ }
157
+
158
+ /* pop every rawgeti + table */
159
+ lua_pop (lua_state , * num_paths_out + 1 );
160
+
161
+ return 0 ;
162
+ }
163
+ #endif
164
+
68
165
/*
69
166
* extract paths from an lmod file
70
167
*/
71
168
int _mii_analysis_lmod (const char * path , char * * * bins_out , int * num_bins_out ) {
72
- char linebuf [MII_ANALYSIS_LINEBUF_SIZE ];
73
- regmatch_t matches [3 ];
74
-
75
169
FILE * f = fopen (path , "r" );
76
170
77
171
if (!f ) {
78
172
mii_error ("Couldn't open %s for reading : %s" , path , strerror (errno ));
79
173
return -1 ;
80
174
}
81
175
176
+ #if !MII_ENABLE_LUA
177
+ char linebuf [MII_ANALYSIS_LINEBUF_SIZE ];
178
+ regmatch_t matches [3 ];
179
+
82
180
while (fgets (linebuf , sizeof linebuf , f )) {
83
181
/* strip off newline */
84
182
int len = strlen (linebuf );
@@ -94,6 +192,38 @@ int _mii_analysis_lmod(const char* path, char*** bins_out, int* num_bins_out) {
94
192
}
95
193
96
194
fclose (f );
195
+ #else
196
+ char * buffer ;
197
+ fseek (f , 0L , SEEK_END );
198
+ long s = ftell (f );
199
+ rewind (f );
200
+ buffer = malloc (s + 1 );
201
+ if ( buffer != NULL ) {
202
+ fread (buffer , s , 1 , f );
203
+ fclose (f ); f = NULL ;
204
+ buffer [s ] = '\0' ;
205
+
206
+ /* get binaries paths */
207
+ char * * bin_paths ;
208
+ int num_paths ;
209
+ if (_mii_analysis_lua_run (lua_state , buffer , & bin_paths , & num_paths )) {
210
+ mii_error ("Error occured when executing %s, skipping" , path );
211
+ free (buffer );
212
+ return -1 ;
213
+ }
214
+
215
+ /* scan every path returned */
216
+ for (int i = 0 ; i < num_paths ; ++ i ) {
217
+ _mii_analysis_scan_path (bin_paths [i ], bins_out , num_bins_out );
218
+ free (bin_paths [i ]);
219
+ }
220
+
221
+ free (bin_paths );
222
+ free (buffer );
223
+ }
224
+ if (f != NULL ) fclose (f );
225
+ #endif
226
+
97
227
return 0 ;
98
228
}
99
229
0 commit comments