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 texset = tex.set
25
26local qualified = { }
27local writeable = { }
28local readable = { }
29local blocked = { }
30local trace_files = false
31local trace_calls = false
32local nofcalls = 0
33local nofrejected = 0
34local logfilename = "sandbox.log"
35
36local function registerstats()
37 statistics.register("sandboxing", function()
38 if trace_files then
39 return string.format("%i calls, %i rejected, logdata in '%s'",nofcalls,nofrejected,logfilename)
40 else
41 return string.format("%i calls, %i rejected",nofcalls,nofrejected)
42 end
43 end)
44 registerstats = false
45end
46
47local function logsandbox(details)
48 local comment = details.comment
49 local result = details.result
50 local arguments = details.arguments
51 for i=1,#arguments do
52 local argument = arguments[i]
53 local t = type(argument)
54 if t == "string" then
55 arguments[i] = quoted(argument)
56 if trace_files and possiblepath(argument) then
57 local q = qualified[argument]
58 if q then
59 local c = q[comment]
60 if c then
61 local r = c[result]
62 if r then
63 c[result] = r + 1
64 else
65 c[result] = r
66 end
67 else
68 q[comment] = {
69 [result] = 1
70 }
71 end
72 else
73 qualified[argument] = {
74 [comment] = {
75 [result] = 1
76 }
77 }
78 end
79 end
80 elseif t == "table" then
81 arguments[i] = fastserialize(argument)
82 else
83 arguments[i] = tostring(argument)
84 end
85 end
86 if trace_calls then
87 report_sandbox("%s(%,t) => %l",details.comment,arguments,result)
88 end
89 nofcalls = nofcalls + 1
90 if not result then
91 nofrejected = nofrejected + 1
92 end
93end
94
95local ioopen = sandbox.original(io.open)
96
97local function logsandboxfiles(name,what,asked,okay)
98
99 if not okay then
100 blocked [asked] = blocked [asked] or 0 + 1
101 elseif what == "*" or what == "w" then
102 writeable[asked] = writeable[asked] or 0 + 1
103 else
104 readable [asked] = readable [asked] or 0 + 1
105 end
106end
107
108function sandbox.logcalls()
109 if not trace_calls then
110 trace_calls = true
111 sandbox.setlogger(logsandbox)
112 if registerstats then
113 registerstats()
114 end
115 end
116end
117
118function sandbox.logfiles()
119 if not trace_files then
120 trace_files = true
121 sandbox.setlogger(logsandbox)
122 sandbox.setfilenamelogger(logsandboxfiles)
123 luatex.registerstopactions(function()
124 table.save(logfilename,{
125 calls = {
126 nofcalls = nofcalls,
127 nofrejected = nofrejected,
128 filenames = qualified,
129 },
130 checkednames = {
131 readable = readable,
132 writeable = writeable,
133 blocked = blocked,
134 },
135 })
136 end)
137 if registerstats then
138 registerstats()
139 end
140 end
141end
142
143trackers.register("sandbox.tracecalls",sandbox.logcalls)
144trackers.register("sandbox.tracefiles",sandbox.logfiles)
145
146local sandboxing = environment.arguments.sandbox
147local debugging = environment.arguments.debug
148
149if sandboxing then
150
151 report_system("enabling sandbox")
152
153 sandbox.enable()
154
155 if type(sandboxing) == "string" then
156 sandboxing = utilities.parsers.settings_to_hash(sandboxing)
157 if sandboxing.calls then
158 sandbox.logcalls()
159 end
160 if sandboxing.files then
161 sandbox.logfiles()
162 end
163 end
164
165
166
167
168
169
170
171 context [[\let\primitive\relax\let\normalprimitive\relax]]
172
173 debug = {
174 traceback = debug.traceback,
175 }
176
177 package.loaded.debug = debug
178
179elseif debugging then
180
181
182
183else
184
185 debug = {
186 traceback = debug.traceback,
187 getinfo = debug.getinfo,
188 sethook = debug.sethook,
189 }
190
191 package.loaded.debug = debug
192
193end
194
195local function setoverloadmode(overloadmode)
196 if overloadmode == "warning" then
197 overloadmode = 3
198 elseif overloadmode == "error" then
199 overloadmode = 4
200 else
201 overloadmode = tonumber(overloadmode)
202 end
203 if overloadmode then
204 texset("overloadmode",overloadmode)
205 end
206end
207
208directives.register("overloadmode", setoverloadmode)
209
210local function processjob()
211
212 local variables = interfaces.variables
213
214 tokens.setters.macro("processjob","","permanent")
215
216 environment.initializefilenames()
217
218 local arguments = environment.arguments
219 local suffix = environment.suffix
220 local filename = environment.filename
221
222 environment.lmtxmode = CONTEXTLMTXMODE
223
224
225
226
227
228 if arguments.directives then
229 directives.enable(arguments.directives)
230 end
231 if arguments.experiments then
232 experiments.enable(arguments.experiments)
233 end
234
235 if arguments.exportimages then
236 arguments.synctex = false
237 end
238
239 if arguments.nosynctex then
240 luatex.synctex.setup {
241 state = variables.never,
242 }
243 elseif arguments.synctex then
244 local state = arguments.synctex
245 if state == true then
246 state = variables.start
247 end
248 luatex.synctex.setup {
249 state = state,
250 method = variables.max,
251 }
252 end
253
254 logs.registerfinalactions(function()
255 logs.pushtarget("log")
256 statistics.showusage("finish")
257 logs.poptarget()
258 end)
259
260 setoverloadmode(arguments.overloadmode)
261
262 if arguments.nocompactfonts then
263 report_system()
264 report_system("compact font mode disabled")
265 report_system()
266 else
267 token.expandmacro("font_enable_compact_font_mode")
268 end
269
270 if not filename or filename == "" then
271
272 elseif suffix == "svg" or arguments.forcesvg then
273
274 report_system("processing svg output: %s",filename)
275
276 context.starttext()
277 context.startTEXpage()
278 context.externalfigure ( { filename }, { conversion = "mp" } )
279 context.stopTEXpage()
280 context.stoptext()
281
282 elseif suffix == "xml" or arguments.forcexml then
283
284
285
286
287
288 report_system("processing as xml: %s",filename)
289
290 context.starttext()
291 context.xmlprocess("main",filename,"")
292 context.stoptext()
293
294 elseif suffix == "cld" or arguments.forcecld then
295
296 report_system("processing as cld: %s",filename)
297
298 context.runfile(filename)
299
300 elseif suffix == "lua" or arguments.forcelua then
301
302
303
304
305 report_system("processing as lua: %s",filename)
306
307 context.starttext()
308 context.ctxlua(string.format('dofile("%s")',filename))
309 context.stoptext()
310
311 elseif suffix == "mp" or arguments.forcemp then
312
313 report_system("processing as metapost: %s",filename)
314
315 context.starttext()
316 context.processMPfigurefile(filename)
317 context.stoptext()
318
319
320
321
322
323
324
325
326
327
328 elseif suffix == "mps" or arguments.forcemps then
329
330 report_system("processing metapost output: %s",filename)
331
332 context.starttext()
333 context.startTEXpage()
334 context.externalfigure { filename }
335 context.stopTEXpage()
336 context.stoptext()
337
338 else
339
340 if arguments.exportimages then
341 context.exportimages()
342 elseif arguments.exportcontent then
343 context.exportcontent()
344 end
345
346
347
348
349
350 if type(arguments.forceinput) == "string" then
351 filename = arguments.forceinput or filename
352 end
353 context.input(filename)
354
355
356 end
357
358 context.finishjob()
359
360end
361
362implement {
363 name = "processjob",
364
365 public = true,
366 onlyonce = true,
367 actions = processjob,
368}
369
370texconfig.firstline = "\\processjob "
371 |