-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
55 lines (48 loc) · 1.99 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
int execl(char const *path, char const *arg0, ...);
int execle(char const *path, char const *arg0, ..., char const *envp[]);
int execlp(char const *file, char const *arg0, ...);
int execv(char const *path, char const *argv[]);
int execve(char const *path, char const *argv[], char const *envp[]);
int execvp(char const *file, char const *argv[]);
int fexecve(int fd, char *const argv[], char *const envp[]);
*/
const libName = Deno.build.os === "linux" ? "libc.so.6" : "libc.dylib";
if(Deno.build.os === "windows") {
throw new Error("Not supported on Windows")
}
const { symbols } = Deno.dlopen(libName, {
execv: {
parameters: ["buffer", "buffer"],
result: "i32",
},
execvp: {
parameters: ["buffer", "buffer"],
result: "i32",
},
});
const nullTerminateStringAsBuffer = (str: string) => {
const encoder = new TextEncoder();
return encoder.encode(str + "\0").buffer;
}
const stringsToNullTerminatedPointerArray = (strings: string[]) => {
const encoder = new TextEncoder();
const buffers = strings.map((str) => encoder.encode(str).buffer);
const ptrs = buffers.map((b) => Deno.UnsafePointer.of(b)).map((ptr) => BigInt(Deno.UnsafePointer.value(ptr)));
return new BigUint64Array([...ptrs, 0n]);
}
const __exec = (type: "execv" | "execvp", path: string, args: string[]): number | never => {
const argv0 = nullTerminateStringAsBuffer(path)
const argvBuffer = stringsToNullTerminatedPointerArray(args);
return symbols[type](argv0, argvBuffer);
}
export const execv = (path: string, args: string[]): number | never => __exec("execv", path, args);
export const execvp = (path: string, args: string[]): number | never => __exec("execvp", path, args);
export function exec(args: string[], env: {[key: string]: string} = {}): number | never {
for (const [key, value] of Object.entries(env)) {
// Execvp inherits environment variables from the parent process
// so we set these via the Deno API
Deno.env.set(key, value)
}
return execvp(args[0], args)
}