1if not modules then modules = { } end modules [ ' l-sandbox ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to luat-lib.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9
10
11
12
13
14
15
16local global = _G
17local next = next
18local unpack = unpack or table . unpack
19local type = type
20local tprint = texio and texio . write_nl or print
21local tostring = tostring
22local format = string . format
23local concat = table . concat
24local sort = table . sort
25local gmatch = string . gmatch
26local gsub = string . gsub
27local requiem = require
28
29sandbox = { }
30local sandboxed = false
31local overloads = { }
32local skiploads = { }
33local initializers = { }
34local finalizers = { }
35local originals = { }
36local comments = { }
37local trace = false
38local logger = false
39local blocked = { }
40
41
42
43local function report ( ... )
44 tprint ( " sandbox ! " . . format ( ... ) )
45end
46
47sandbox . report = report
48
49function sandbox . setreporter ( r )
50 report = r
51 sandbox . report = r
52end
53
54function sandbox . settrace ( v )
55 trace = v
56end
57
58function sandbox . setlogger ( l )
59 logger = type ( l ) = = " function " and l or false
60end
61
62local function register ( func , overload , comment )
63 if type ( func ) = = " function " then
64 if type ( overload ) = = " string " then
65 comment = overload
66 overload = nil
67 end
68 local function f ( ... )
69 if sandboxed then
70 local overload = overloads [ f ]
71 if overload then
72 if logger then
73 local result = { overload ( func , ... ) }
74 logger {
75 comment = comments [ f ] or tostring ( f ) ,
76 arguments = { ... } ,
77 result = result [ 1 ] and true or false ,
78 }
79 return unpack ( result )
80 else
81 return overload ( func , ... )
82 end
83 else
84
85 end
86 else
87 return func ( ... )
88 end
89 end
90 if comment then
91 comments [ f ] = comment
92 if trace then
93 report ( " registering function: %s " , comment )
94 end
95 end
96 overloads [ f ] = overload or false
97 originals [ f ] = func
98 return f
99 end
100end
101
102local function redefine ( func , comment )
103 if type ( func ) = = " function " then
104 skiploads [ func ] = comment or comments [ func ] or " unknown "
105 if overloads [ func ] = = false then
106 overloads [ func ] = nil
107 end
108 end
109end
110
111sandbox . register = register
112sandbox . redefine = redefine
113
114function sandbox . original ( func )
115 return originals and originals [ func ] or func
116end
117
118function sandbox . overload ( func , overload , comment )
119 comment = comment or comments [ func ] or " ? "
120 if type ( func ) ~ = " function " then
121 if trace then
122 report ( " overloading unknown function: %s " , comment )
123 end
124 elseif type ( overload ) ~ = " function " then
125 if trace then
126 report ( " overloading function with bad overload: %s " , comment )
127 end
128 elseif overloads [ func ] = = nil then
129 if trace then
130 report ( " function is not registered: %s " , comment )
131 end
132 elseif skiploads [ func ] then
133 if trace then
134 report ( " function is not skipped: %s " , comment )
135 end
136 else
137 if trace then
138 report ( " overloading function: %s " , comment )
139 end
140 overloads [ func ] = overload
141 end
142 return func
143end
144
145local function whatever ( specification , what , target )
146 if type ( specification ) ~ = " table " then
147 report ( " %s needs a specification " , what )
148 elseif type ( specification . category ) ~ = " string " or type ( specification . action ) ~ = " function " then
149 report ( " %s needs a category and action " , what )
150 elseif not sandboxed then
151 target [ # target + 1 ] = specification
152 elseif trace then
153 report ( " already enabled, discarding %s " , what )
154 end
155end
156
157function sandbox . initializer ( specification )
158 whatever ( specification , " initializer " , initializers )
159end
160
161function sandbox . finalizer ( specification )
162 whatever ( specification , " finalizer " , finalizers )
163end
164
165function require ( name )
166 local n = gsub ( name , " ^.*[\\/] " , " " )
167 local n = gsub ( n , " [%.].*$ " , " " )
168 local b = blocked [ n ]
169 if b = = false then
170 return nil
171 elseif b then
172 if trace then
173 report ( " using blocked: %s " , n )
174 end
175 return b
176 else
177 if trace then
178 report ( " requiring: %s " , name )
179 end
180 return requiem ( name )
181 end
182end
183
184function blockrequire ( name , lib )
185 if trace then
186 report ( " preventing reload of: %s " , name )
187 end
188 blocked [ name ] = lib or _G [ name ] or false
189end
190
191function sandbox . enable ( )
192 if not sandboxed then
193 debug = {
194 traceback = debug . traceback ,
195 }
196 for i = 1 , # initializers do
197 initializers [ i ] . action ( )
198 end
199 for i = 1 , # finalizers do
200 finalizers [ i ] . action ( )
201 end
202 local nnot = 0
203 local nyes = 0
204 local cnot = { }
205 local cyes = { }
206 local skip = { }
207 for k , v in next , overloads do
208 local c = comments [ k ]
209 if v then
210 if c then
211 cyes [ # cyes + 1 ] = c
212 else
213 nyes = nyes + 1
214 end
215 else
216 if c then
217 cnot [ # cnot + 1 ] = c
218 else
219 nnot = nnot + 1
220 end
221 end
222 end
223 for k , v in next , skiploads do
224 skip [ # skip + 1 ] = v
225 end
226 if # cyes > 0 then
227 sort ( cyes )
228 report ( " overloaded known: %s " , concat ( cyes , " | " ) )
229 end
230 if nyes > 0 then
231 report ( " overloaded unknown: %s " , nyes )
232 end
233 if # cnot > 0 then
234 sort ( cnot )
235 report ( " not overloaded known: %s " , concat ( cnot , " | " ) )
236 end
237 if nnot > 0 then
238 report ( " not overloaded unknown: %s " , nnot )
239 end
240 if # skip > 0 then
241 sort ( skip )
242 report ( " not overloaded redefined: %s " , concat ( skip , " | " ) )
243 end
244
245 initializers = nil
246 finalizers = nil
247 originals = nil
248 sandboxed = true
249 end
250end
251
252blockrequire ( " lfs " , lfs )
253blockrequire ( " io " , io )
254blockrequire ( " os " , os )
255blockrequire ( " ffi " , ffi )
256
257
258
259
260
261
262
263
264local function supported ( library )
265 local l = _G [ library ]
266
267
268
269
270
271 return l
272end
273
274
275
276
277
278
279
280
281
282loadfile = register ( loadfile , " loadfile " )
283
284if supported ( " lua " ) then
285 lua . openfile = register ( lua . openfile , " lua.openfile " )
286end
287
288if supported ( " io " ) then
289 io . open = register ( io . open , " io.open " )
290 io . popen = register ( io . popen , " io.popen " )
291 io . lines = register ( io . lines , " io.lines " )
292 io . output = register ( io . output , " io.output " )
293 io . input = register ( io . input , " io.input " )
294end
295
296if supported ( " os " ) then
297 os . execute = register ( os . execute , " os.execute " )
298 os . spawn = register ( os . spawn , " os.spawn " )
299 os . exec = register ( os . exec , " os.exec " )
300 os . rename = register ( os . rename , " os.rename " )
301 os . remove = register ( os . remove , " os.remove " )
302end
303
304if supported ( " lfs " ) then
305 lfs . chdir = register ( lfs . chdir , " lfs.chdir " )
306 lfs . mkdir = register ( lfs . mkdir , " lfs.mkdir " )
307 lfs . rmdir = register ( lfs . rmdir , " lfs.rmdir " )
308 lfs . isfile = register ( lfs . isfile , " lfs.isfile " )
309 lfs . isdir = register ( lfs . isdir , " lfs.isdir " )
310 lfs . attributes = register ( lfs . attributes , " lfs.attributes " )
311 lfs . dir = register ( lfs . dir , " lfs.dir " )
312 lfs . lock_dir = register ( lfs . lock_dir , " lfs.lock_dir " )
313 lfs . touch = register ( lfs . touch , " lfs.touch " )
314 lfs . link = register ( lfs . link , " lfs.link " )
315 lfs . setmode = register ( lfs . setmode , " lfs.setmode " )
316 lfs . readlink = register ( lfs . readlink , " lfs.readlink " )
317 lfs . shortname = register ( lfs . shortname , " lfs.shortname " )
318 lfs . symlinkattributes = register ( lfs . symlinkattributes , " lfs.symlinkattributes " )
319end
320
321 |