1 module exec.stupidlocal;
2 
3 import exec.iexecprovider;
4 
5 import vibe.core.core: sleep, runTask;
6 import core.time : msecs;
7 
8 import std.process;
9 import std.typecons: Tuple;
10 import std.file: exists, remove, tempDir;
11 import std.stdio: File;
12 import std.random: uniform;
13 import std.string: format;
14 
15 /++
16 	Stupid local executor which just runs rdmd and passes the source to it
17 	and outputs the executes binary's output.
18 
19 	Warning:
20 		UNSAFE BECUASE CODE IS RUN UNFILTERED AND NOT IN A SANDBOX
21 +/
22 class StupidLocal: IExecProvider
23 {
24 	private File getTempFile()
25 	{
26 		auto tempdir = tempDir();
27 
28 		static string randomName()
29 		{
30 			enum Length = 10;
31 			char[Length] res;
32 			foreach (ref c; res) {
33 				c = cast(char)('a' + uniform(0, 'z'-'a'));
34 			}
35 			return res.idup;
36 		}
37 
38 		string tempname;
39 		do {
40 			tempname = "%s/temp_dlang_tour_%s.d".format(tempdir, randomName());
41 		} while (exists(tempname));
42 
43 		File tempfile;
44 		tempfile.open(tempname, "wb");
45 		return tempfile;
46 	}
47 
48 	Tuple!(string, "output", bool, "success") compileAndExecute(string source)
49 	{
50 		typeof(return) result;
51 		auto task = runTask(() {
52 			auto tmpfile = getTempFile();
53 			scope(exit) tmpfile.name.remove;
54 
55 			tmpfile.write(source);
56 			tmpfile.close();
57 			auto rdmd = execute(["rdmd", tmpfile.name]);
58 			result.success = rdmd.status == 0;
59 			result.output = rdmd.output;
60 		});
61 
62 		while (task.running)
63 			sleep(300.msecs);
64 
65 		return result;
66 	}
67 }