Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/core/posix-node/src/spawn.zig
1067 views
1
const c = @import("c.zig");
2
const node = @import("node.zig");
3
const util = @import("util.zig");
4
const std = @import("std");
5
const spawn = @cImport({
6
@cInclude("spawn.h");
7
@cInclude("sched.h");
8
@cInclude("signal.h");
9
});
10
const builtin = @import("builtin");
11
12
pub fn register(env: c.napi_env, exports: c.napi_value) !void {
13
try node.registerFunction(env, exports, "_posix_spawn", posix_spawn);
14
}
15
16
// int
17
// posix_spawn(pid_t *restrict pid, const char *restrict path,
18
// const posix_spawn_file_actions_t *file_actions,
19
// const posix_spawnattr_t *restrict attrp,
20
// char *const argv[restrict], char *const envp[restrict]);
21
22
// returns the pid
23
// posix_spawn(path: string, fileActions, attributes, argv:string[], envp:string[]) : number
24
25
fn posix_spawn(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
26
const args = node.getArgv(env, info, 6) catch return null;
27
28
var path = node.valueToString(env, args[0], "path") catch return null;
29
defer std.c.free(path);
30
31
var file_actions: spawn.posix_spawn_file_actions_t = undefined;
32
if (spawn.posix_spawn_file_actions_init(&file_actions) != 0) {
33
node.throwErrno(env, "error in posix_spawn calling spawn.posix_spawn_file_actions_init");
34
return null;
35
}
36
37
const lenFileActions = node.arrayLength(env, args[1], "fileActions") catch return null;
38
var index: u32 = 0;
39
const bufsize = 1024; // also used for a path below
40
var buf: [bufsize]u8 = undefined;
41
while (index < lenFileActions) : (index += 1) {
42
const fileAction = node.getArrayElement(env, args[1], index, "fileActions") catch return null;
43
const action = node.getArrayElement(env, fileAction, 0, "fileAction") catch return null;
44
node.stringFromValue(env, action, "fileAction[0]", bufsize, &buf) catch return null;
45
// it should be "addclose", "addopen", or "adddup2".
46
if (buf[3] == "c"[0]) { // ["addclose", fd]
47
const fd = node.i32FromValue(env, node.getArrayElement(env, fileAction, 1, "fd") catch return null, "fd") catch return null;
48
if (spawn.posix_spawn_file_actions_addclose(&file_actions, fd) != 0) {
49
node.throw(env, "call to posix_spawn_file_actions_addclose failed") catch return null;
50
}
51
} else if (buf[3] == "o"[0]) { // ["addopen", fd, path, oflag, mode]
52
const fd = node.i32FromValue(env, node.getArrayElement(env, fileAction, 1, "fd") catch return null, "fd") catch return null;
53
node.stringFromValue(env, node.getArrayElement(env, fileAction, 2, "path") catch return null, "path", bufsize, &buf) catch return null;
54
const oflag = node.i32FromValue(env, node.getArrayElement(env, fileAction, 3, "oflag") catch return null, "oflag") catch return null;
55
const mode = @intCast(spawn.mode_t, node.u32FromValue(env, node.getArrayElement(env, fileAction, 4, "mode") catch return null, "mode") catch return null);
56
if (spawn.posix_spawn_file_actions_addopen(&file_actions, fd, &buf, oflag, mode) != 0) {
57
node.throw(env, "call to posix_spawn_file_actions_addopen failed") catch return null;
58
}
59
} else if (buf[3] == "d"[0]) { // ["adddup2", fd, new_fd]
60
const fd = node.i32FromValue(env, node.getArrayElement(env, fileAction, 1, "fd") catch return null, "fd") catch return null;
61
const new_fd = node.i32FromValue(env, node.getArrayElement(env, fileAction, 2, "new_fd") catch return null, "new_fd") catch return null;
62
if (spawn.posix_spawn_file_actions_adddup2(&file_actions, fd, new_fd) != 0) {
63
node.throw(env, "call to posix_spawn_file_actions_adddup2 failed") catch return null;
64
}
65
} else {
66
node.throw(env, "invalid fileAction") catch return null;
67
}
68
}
69
70
var attr: spawn.posix_spawnattr_t = undefined;
71
if (spawn.posix_spawnattr_init(&attr) != 0) {
72
node.throwErrno(env, "error in posix_spawn calling spawn.posix_spawnattr_init");
73
return null;
74
}
75
if (builtin.target.os.tag == .linux) {
76
// posix_spawnattr_setschedparam and posix_spawnattr_setschedpolicy seem to not exist on macos (maybe only on linux?)
77
if (node.hasNamedProperty(env, args[2], "sched_priority", "property of spawnattr") catch return null) {
78
const sched_priority = node.i32_from_object(env, args[2], "sched_priority") catch return null;
79
var schedparam = std.mem.zeroInit(spawn.sched_param, .{});
80
schedparam.sched_priority = sched_priority;
81
if (spawn.posix_spawnattr_setschedparam(&attr, &schedparam) != 0) {
82
node.throw(env, "call to posix_spawnattr_setpgroup failed") catch return null;
83
}
84
}
85
if (node.hasNamedProperty(env, args[2], "schedpolicy", "property of spawnattr") catch return null) {
86
const schedpolicy = node.i32_from_object(env, args[2], "schedpolicy") catch return null;
87
if (spawn.posix_spawnattr_setschedpolicy(&attr, schedpolicy) != 0) {
88
node.throw(env, "call to posix_spawnattr_setschedpolicy failed") catch return null;
89
}
90
}
91
}
92
if (node.hasNamedProperty(env, args[2], "flags", "property of spawnattr") catch return null) {
93
const flags = node.i16_from_object(env, args[2], "flags") catch return null;
94
if (spawn.posix_spawnattr_setflags(&attr, flags) != 0) {
95
node.throw(env, "call to posix_spawnattr_setflags failed") catch return null;
96
}
97
}
98
if (node.hasNamedProperty(env, args[2], "pgroup", "property of spawnattr") catch return null) {
99
const pgroup = node.i32_from_object(env, args[2], "pgroup") catch return null;
100
if (spawn.posix_spawnattr_setpgroup(&attr, pgroup) != 0) {
101
node.throw(env, "call to posix_spawnattr_setpgroup failed") catch return null;
102
}
103
}
104
if (node.hasNamedProperty(env, args[2], "sigmask", "property of spawnattr") catch return null) {
105
const sigmask = node.getNamedProperty(env, args[2], "sigmask", "property of spawnattr") catch return null;
106
var sigset: spawn.sigset_t = undefined;
107
sigset_t_fromArray(env, sigmask, "sigmask", &sigset) catch return null;
108
if (spawn.posix_spawnattr_setsigmask(&attr, &sigset) != 0) {
109
node.throw(env, "call to posix_spawnattr_setsigmask failed") catch return null;
110
}
111
}
112
if (node.hasNamedProperty(env, args[2], "sigdefault", "property of spawnattr") catch return null) {
113
const sigdefault = node.getNamedProperty(env, args[2], "sigdefault", "property of spawnattr") catch return null;
114
var sigset: spawn.sigset_t = undefined;
115
sigset_t_fromArray(env, sigdefault, "sigset", &sigset) catch return null;
116
if (spawn.posix_spawnattr_setsigdefault(&attr, &sigset) != 0) {
117
node.throw(env, "call to posix_spawnattr_setsigdefault failed") catch return null;
118
}
119
}
120
121
var argv = node.valueToArrayOfStrings(env, args[3], "argv") catch return null;
122
defer util.freeArrayOfStrings(argv);
123
124
var envp = node.valueToArrayOfStrings(env, args[4], "envp") catch return null;
125
defer util.freeArrayOfStrings(envp);
126
127
var p = node.valueToBool(env, args[5], "p") catch return null;
128
129
var pid: spawn.pid_t = undefined;
130
var ret = if (p) spawn.posix_spawnp(&pid, path, &file_actions, &attr, argv, envp) else spawn.posix_spawn(&pid, path, &file_actions, &attr, argv, envp);
131
if (ret != 0) {
132
node.throwErrno(env, "error in posix_spawn calling spawn.posix_spawn");
133
return null;
134
}
135
return node.create_i32(env, pid, "pid") catch return null;
136
}
137
138
fn sigset_t_fromArray(env: c.napi_env, array: c.napi_value, comptime message: [:0]const u8, setPtr: *spawn.sigset_t) !void {
139
if (spawn.sigemptyset(setPtr) != 0) {
140
return node.throw(env, "failed to init signal set -- " ++ message);
141
}
142
const len = try node.arrayLength(env, array, "sigset_t_fromArray");
143
var i: i32 = 0;
144
while (i < len) : (i += 1) {
145
const s = try node.getArrayElement(env, array, @intCast(u32, i), "getting signal from set");
146
const signum = try node.i32FromValue(env, s, "signum");
147
if (spawn.sigaddset(setPtr, signum) != 0) {
148
return node.throw(env, "failed to add a signal to the set -- " ++ message);
149
}
150
}
151
}
152
153