1if not modules then modules = { } end modules ['cont-run'] = {
2 version = 1.001,
3 comment = "companion to cont-yes.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
13local type, tostring = type, tostring
14
15local report_sandbox = logs.reporter("sandbox","call")
16local report_system = logs.reporter("system")
17local fastserialize = table.fastserialize
18local quoted = string.quoted
19local possiblepath = sandbox.possiblepath
20
21local context = context
22local implement = interfaces.implement
23
24local qualified = { }
25local writeable = { }
26local readable = { }
27local blocked = { }
28local trace_files = false
29local trace_calls = false
30local nofcalls = 0
31local nofrejected = 0
32local logfilename = "sandbox.log"
33
34local function registerstats()
35 statistics.register("sandboxing", function()
36 if trace_files then
37 return string.format("%i calls, %i rejected, logdata in '%s'",nofcalls,nofrejected,logfilename)
38 else
39 return string.format("%i calls, %i rejected",nofcalls,nofrejected)
40 end
41 end)
42 registerstats = false
43end
44
45local function logsandbox(details)
46 local comment = details.comment
47 local result = details.result
48 local arguments = details.arguments
49 for i=1,#arguments do
50 local argument = arguments[i]
51 local t = type(argument)
52 if t == "string" then
53 arguments[i] = quoted(argument)
54 if trace_files and possiblepath(argument) then
55 local q = qualified[argument]
56 if q then
57 local c = q[comment]
58 if c then
59 local r = c[result]
60 if r then
61 c[result] = r + 1
62 else
63 c[result] = r
64 end
65 else
66 q[comment] = {
67 [result] = 1
68 }
69 end
70 else
71 qualified[argument] = {
72 [comment] = {
73 [result] = 1
74 }
75 }
76 end
77 end
78 elseif t == "table" then
79 arguments[i] = fastserialize(argument)
80 else
81 arguments[i] = tostring(argument)
82 end
83 end
84 if trace_calls then
85 report_sandbox("%s(%,t) => %l",details.comment,arguments,result)
86 end
87 nofcalls = nofcalls + 1
88 if not result then
89 nofrejected = nofrejected + 1
90 end
91end
92
93local ioopen = sandbox.original(io.open)
94
95local function logsandboxfiles(name,what,asked,okay)
96
97 if not okay then
98 blocked [asked] = blocked [asked] or 0 + 1
99 elseif what == "*" or what == "w" then
100 writeable[asked] = writeable[asked] or 0 + 1
101 else
102 readable [asked] = readable [asked] or 0 + 1
103 end
104end
105
106function sandbox.logcalls()
107 if not trace_calls then
108 trace_calls = true
109 sandbox.setlogger(logsandbox)
110 if registerstats then
111 registerstats()
112 end
113 end
114end
115
116function sandbox.logfiles()
117 if not trace_files then
118 trace_files = true
119 sandbox.setlogger(logsandbox)
120 sandbox.setfilenamelogger(logsandboxfiles)
121 luatex.registerstopactions(function()
122 table.save(logfilename,{
123 calls = {
124 nofcalls = nofcalls,
125 nofrejected = nofrejected,
126 filenames = qualified,
127 },
128 checkednames = {
129 readable = readable,
130 writeable = writeable,
131 blocked = blocked,
132 },
133 })
134 end)
135 if registerstats then
136 registerstats()
137 end
138 end
139end
140
141trackers.register("sandbox.tracecalls",sandbox.logcalls)
142trackers.register("sandbox.tracefiles",sandbox.logfiles)
143
144local sandboxing = environment.arguments.sandbox
145local debugging = environment.arguments.debug
146
147if sandboxing then
148
149 report_system("enabling sandbox")
150
151 sandbox.enable()
152
153 if type(sandboxing) == "string" then
154 sandboxing = utilities.parsers.settings_to_hash(sandboxing)
155 if sandboxing.calls then
156 sandbox.logcalls()
157 end
158 if sandboxing.files then
159 sandbox.logfiles()
160 end
161 end
162
163
164
165
166
167
168
169 context [[\let\primitive\relax\let\normalprimitive\relax]]
170
171 debug = {
172 traceback = debug.traceback,
173 }
174
175 package.loaded.debug = debug
176
177elseif debugging then
178
179
180
181else
182
183 debug = {
184 traceback = debug.traceback,
185 getinfo = debug.getinfo,
186 sethook = debug.sethook,
187 }
188
189 package.loaded.debug = debug
190
191end
192
193local function processjob()
194
195 tokens.setters.macro("processjob","")
196
197 environment.initializefilenames()
198
199 local arguments = environment.arguments
200 local suffix = environment.suffix
201 local filename = environment.filename
202
203 environment.lmtxmode = false
204
205 if arguments.nosynctex then
206 luatex.synctex.setup {
207 state = interfaces.variables.never,
208 }
209 elseif arguments.synctex then
210 luatex.synctex.setup {
211 state = interfaces.variables.start,
212 method = interfaces.variables.max,
213 }
214 end
215
216 if not filename or filename == "" then
217
218 elseif suffix == "xml" or arguments.forcexml then
219
220
221
222
223
224 report_system("processing as xml: %s",filename)
225
226 context.starttext()
227 context.xmlprocess("main",filename,"")
228 context.stoptext()
229
230 elseif suffix == "cld" or arguments.forcecld then
231
232 report_system("processing as cld: %s",filename)
233
234 context.runfile(filename)
235
236 elseif suffix == "lua" or arguments.forcelua then
237
238
239
240
241 report_system("processing as lua: %s",filename)
242
243 context.starttext()
244 context.ctxlua(string.format('dofile("%s")',filename))
245 context.stoptext()
246
247 elseif suffix == "mp" or arguments.forcemp then
248
249 report_system("processing as metapost: %s",filename)
250
251 context.starttext()
252 context.processMPfigurefile(filename)
253 context.stoptext()
254
255
256
257
258
259
260
261
262
263
264 elseif suffix == "mps" or arguments.forcemps then
265
266 report_system("processing metapost output: %s",filename)
267
268 context.starttext()
269 context.startTEXpage()
270 context.externalfigure { filename }
271 context.stopTEXpage()
272 context.stoptext()
273
274 else
275
276
277
278
279
280 context.input(filename)
281
282
283 end
284
285 context.finishjob()
286
287end
288
289implement {
290 name = "processjob",
291 public = true,
292 onlyonce = true,
293 actions = processjob,
294}
295 |