mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
data/std/process.mt
ADDED
|
@@ -0,0 +1,837 @@
|
|
|
1
|
+
import std.c.process as c
|
|
2
|
+
import std.mem.arena as arena
|
|
3
|
+
import std.mem.heap as heap
|
|
4
|
+
import std.str as text
|
|
5
|
+
import std.string as string
|
|
6
|
+
import std.vec as vec
|
|
7
|
+
|
|
8
|
+
public struct EnvironmentEntry:
|
|
9
|
+
name: str
|
|
10
|
+
value: str
|
|
11
|
+
|
|
12
|
+
public struct ExitStatus:
|
|
13
|
+
exit_code: long
|
|
14
|
+
term_signal: int
|
|
15
|
+
|
|
16
|
+
public struct CaptureResult:
|
|
17
|
+
stdout: string.String
|
|
18
|
+
stderr: string.String
|
|
19
|
+
status: ExitStatus
|
|
20
|
+
|
|
21
|
+
public struct ProcessError:
|
|
22
|
+
code: int
|
|
23
|
+
message: string.String
|
|
24
|
+
|
|
25
|
+
public struct ReadResult:
|
|
26
|
+
ready: bool
|
|
27
|
+
closed: bool
|
|
28
|
+
data: string.String
|
|
29
|
+
|
|
30
|
+
public struct ChildProcess:
|
|
31
|
+
pid: int
|
|
32
|
+
stdin_fd: int
|
|
33
|
+
stdout_fd: int
|
|
34
|
+
stderr_fd: int
|
|
35
|
+
|
|
36
|
+
public struct PtyProcess:
|
|
37
|
+
pid: int
|
|
38
|
+
master_fd: int
|
|
39
|
+
|
|
40
|
+
struct PreparedCommand:
|
|
41
|
+
storage: arena.Arena
|
|
42
|
+
file: cstr
|
|
43
|
+
args: ptr[ptr[char]]
|
|
44
|
+
env: ptr[ptr[char]]?
|
|
45
|
+
cwd: cstr?
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
function take_owned_string(data: ptr[char]?, len: ptr_uint) -> string.String:
|
|
49
|
+
if data == null:
|
|
50
|
+
if len != 0:
|
|
51
|
+
fatal(c"process.take_owned_string missing storage")
|
|
52
|
+
|
|
53
|
+
return string.String.create()
|
|
54
|
+
|
|
55
|
+
return unsafe: string.String(data = ptr[ubyte]<-data, len = len, capacity = len, owns_storage = true)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
function safe_text_view(value: string.String) -> Option[str]:
|
|
59
|
+
return text.utf8_byte_span_as_str(unsafe: span[ubyte](data = ptr[ubyte]<-value.data, len = value.len))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
function empty_environment() -> span[EnvironmentEntry]:
|
|
63
|
+
return zero[span[EnvironmentEntry]]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Returns the parent process's environment entries. Each entry is a
|
|
67
|
+
## "NAME=VALUE" string parsed from the POSIX `environ` array. Entries
|
|
68
|
+
## with empty names (broken entries) are silently skipped.
|
|
69
|
+
public function parent_environment() -> vec.Vec[EnvironmentEntry]:
|
|
70
|
+
var result = vec.Vec[EnvironmentEntry].create()
|
|
71
|
+
let count = c.mt_process_environ_length()
|
|
72
|
+
if count == 0:
|
|
73
|
+
return result
|
|
74
|
+
result.reserve(count)
|
|
75
|
+
unsafe:
|
|
76
|
+
let raw_ptr_opt = c.mt_process_environ_accessor()
|
|
77
|
+
if raw_ptr_opt == null:
|
|
78
|
+
return result
|
|
79
|
+
let env_array = read(raw_ptr_opt)
|
|
80
|
+
var i: ptr_uint = 0
|
|
81
|
+
while i < count:
|
|
82
|
+
let entry_cstr = read(env_array + i)
|
|
83
|
+
let len = find_null_byte(entry_cstr, 0)
|
|
84
|
+
if len == 0:
|
|
85
|
+
i += 1
|
|
86
|
+
continue
|
|
87
|
+
var eq_pos: ptr_uint = 0
|
|
88
|
+
while eq_pos < len and read(entry_cstr + eq_pos) != 61:
|
|
89
|
+
eq_pos += 1
|
|
90
|
+
if eq_pos == 0 or eq_pos >= len:
|
|
91
|
+
i += 1
|
|
92
|
+
continue
|
|
93
|
+
var nname = string.String.create()
|
|
94
|
+
nname.reserve(eq_pos)
|
|
95
|
+
var ni: ptr_uint = 0
|
|
96
|
+
while ni < eq_pos:
|
|
97
|
+
nname.push_byte(ubyte<-(unsafe: read(entry_cstr + ni)))
|
|
98
|
+
ni += 1
|
|
99
|
+
var nvalue = string.String.create()
|
|
100
|
+
let vlen = len - eq_pos - 1
|
|
101
|
+
if vlen > 0:
|
|
102
|
+
nvalue.reserve(vlen)
|
|
103
|
+
var vi: ptr_uint = 0
|
|
104
|
+
while vi < vlen:
|
|
105
|
+
nvalue.push_byte(ubyte<-(unsafe: read(entry_cstr + eq_pos + 1 + vi)))
|
|
106
|
+
vi += 1
|
|
107
|
+
result.push(EnvironmentEntry(
|
|
108
|
+
name = nname.as_str(),
|
|
109
|
+
value = nvalue.as_str()
|
|
110
|
+
))
|
|
111
|
+
i += 1
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## Scan `data` (pointer to a NUL-terminated buffer) from `start` for the
|
|
116
|
+
## first 0 byte. Returns the byte offset at which the NUL was found.
|
|
117
|
+
function find_null_byte(data: ptr[char], start: ptr_uint) -> ptr_uint:
|
|
118
|
+
var i = start
|
|
119
|
+
unsafe:
|
|
120
|
+
while read(data + i) != 0:
|
|
121
|
+
i += 1
|
|
122
|
+
return i
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
## Like `capture` but inherits the parent environment and merges
|
|
126
|
+
## `extra_env` entries (extra entries override parent entries with the
|
|
127
|
+
## same name). When `extra_env` is empty, identical to `capture`.
|
|
128
|
+
public function capture_inheriting_env(
|
|
129
|
+
command: span[str],
|
|
130
|
+
cwd: Option[str],
|
|
131
|
+
extra_env: span[EnvironmentEntry]
|
|
132
|
+
) -> Result[CaptureResult, ProcessError]:
|
|
133
|
+
if extra_env.len == 0:
|
|
134
|
+
return capture_internal(command, cwd, empty_environment())
|
|
135
|
+
var env_vec = parent_environment()
|
|
136
|
+
merge_environment(ref_of(env_vec), extra_env)
|
|
137
|
+
let env_span = env_vec.as_span()
|
|
138
|
+
let result = capture_internal(command, cwd, env_span)
|
|
139
|
+
env_vec.release()
|
|
140
|
+
return result
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
## Like `spawn` but inherits the parent environment and merges
|
|
144
|
+
## `extra_env` entries.
|
|
145
|
+
public function spawn_inheriting_env(
|
|
146
|
+
command: span[str],
|
|
147
|
+
cwd: Option[str],
|
|
148
|
+
extra_env: span[EnvironmentEntry]
|
|
149
|
+
) -> Result[ChildProcess, ProcessError]:
|
|
150
|
+
if extra_env.len == 0:
|
|
151
|
+
return spawn_internal(command, cwd, empty_environment())
|
|
152
|
+
var env_vec = parent_environment()
|
|
153
|
+
merge_environment(ref_of(env_vec), extra_env)
|
|
154
|
+
let env_span = env_vec.as_span()
|
|
155
|
+
let result = spawn_internal(command, cwd, env_span)
|
|
156
|
+
env_vec.release()
|
|
157
|
+
return result
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
## Merge `extra` entries into `base`, overwriting base entries that share
|
|
161
|
+
## the same name. New entries (names not in base) are appended.
|
|
162
|
+
function merge_environment(base: ref[vec.Vec[EnvironmentEntry]], extra: span[EnvironmentEntry]) -> void:
|
|
163
|
+
var ei: ptr_uint = 0
|
|
164
|
+
while ei < extra.len:
|
|
165
|
+
let entry = unsafe: read(extra.data + ei)
|
|
166
|
+
var found = false
|
|
167
|
+
var bi: ptr_uint = 0
|
|
168
|
+
while bi < base.len():
|
|
169
|
+
let bp = base.get(bi) else:
|
|
170
|
+
break
|
|
171
|
+
if unsafe: read(bp).name.equal(entry.name):
|
|
172
|
+
unsafe: read(bp) = entry
|
|
173
|
+
found = true
|
|
174
|
+
break
|
|
175
|
+
bi += 1
|
|
176
|
+
if not found:
|
|
177
|
+
base.push(entry)
|
|
178
|
+
ei += 1
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
function pointer_storage_bytes(count: ptr_uint) -> ptr_uint:
|
|
182
|
+
let pointer_size = size_of(ptr[char])
|
|
183
|
+
if heap.mul_overflows(count, pointer_size):
|
|
184
|
+
fatal(c"process pointer storage overflow")
|
|
185
|
+
|
|
186
|
+
return count * pointer_size
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
function clear_pointer_slot(slot: ptr[ptr[char]]) -> void:
|
|
190
|
+
let slot_bytes = size_of(ptr[char])
|
|
191
|
+
var index: ptr_uint = 0
|
|
192
|
+
unsafe:
|
|
193
|
+
let buffer = ptr[ubyte]<-slot
|
|
194
|
+
while index < slot_bytes:
|
|
195
|
+
read(buffer + index) = 0
|
|
196
|
+
index += 1
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
function total_storage_bytes(command: span[str], cwd: Option[str], env: span[EnvironmentEntry]) -> ptr_uint:
|
|
200
|
+
var total = pointer_storage_bytes(command.len + 1)
|
|
201
|
+
if env.len != 0:
|
|
202
|
+
total += pointer_storage_bytes(env.len + 1)
|
|
203
|
+
|
|
204
|
+
var index: ptr_uint = 0
|
|
205
|
+
while index < command.len:
|
|
206
|
+
let value = unsafe: read(command.data + index)
|
|
207
|
+
if total > heap.ptr_uint_max - (value.len + 1):
|
|
208
|
+
fatal(c"process command storage overflow")
|
|
209
|
+
total += value.len + 1
|
|
210
|
+
index += 1
|
|
211
|
+
|
|
212
|
+
match cwd:
|
|
213
|
+
Option.some as payload:
|
|
214
|
+
if total > heap.ptr_uint_max - (payload.value.len + 1):
|
|
215
|
+
fatal(c"process cwd storage overflow")
|
|
216
|
+
total += payload.value.len + 1
|
|
217
|
+
Option.none:
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
index = 0
|
|
221
|
+
while index < env.len:
|
|
222
|
+
let entry = unsafe: read(env.data + index)
|
|
223
|
+
if total > heap.ptr_uint_max - (entry.name.len + 1):
|
|
224
|
+
fatal(c"process env storage overflow")
|
|
225
|
+
total += entry.name.len + 1
|
|
226
|
+
if total > heap.ptr_uint_max - (entry.value.len + 1):
|
|
227
|
+
fatal(c"process env storage overflow")
|
|
228
|
+
total += entry.value.len + 1
|
|
229
|
+
index += 1
|
|
230
|
+
|
|
231
|
+
return total
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
function write_environment_value(space: ref[arena.Arena], entry: EnvironmentEntry) -> cstr:
|
|
235
|
+
let size_bytes = entry.name.len + entry.value.len + 2
|
|
236
|
+
let memory = space.alloc_bytes(size_bytes) else:
|
|
237
|
+
fatal(c"process env storage exhausted")
|
|
238
|
+
|
|
239
|
+
unsafe:
|
|
240
|
+
let buffer = ptr[char]<-memory
|
|
241
|
+
if entry.name.len != 0:
|
|
242
|
+
heap.copy_bytes(ptr[ubyte]<-buffer, ptr[ubyte]<-entry.name.data, entry.name.len)
|
|
243
|
+
read(ptr[ubyte]<-buffer + entry.name.len) = 61
|
|
244
|
+
if entry.value.len != 0:
|
|
245
|
+
heap.copy_bytes(ptr[ubyte]<-buffer + entry.name.len + 1, ptr[ubyte]<-entry.value.data, entry.value.len)
|
|
246
|
+
read(buffer + entry.name.len + 1 + entry.value.len) = zero[char]
|
|
247
|
+
return cstr<-buffer
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
function prepare_command(
|
|
251
|
+
command: span[str],
|
|
252
|
+
cwd: Option[str],
|
|
253
|
+
env: span[EnvironmentEntry]
|
|
254
|
+
) -> Result[PreparedCommand, ProcessError]:
|
|
255
|
+
if command.len == 0:
|
|
256
|
+
return Result[PreparedCommand, ProcessError].failure(error= ProcessError(
|
|
257
|
+
code = -1,
|
|
258
|
+
message = string.String.from_str("process command cannot be empty")
|
|
259
|
+
))
|
|
260
|
+
|
|
261
|
+
let total_bytes = total_storage_bytes(command, cwd, env)
|
|
262
|
+
var storage = arena.create_aligned(total_bytes, align_of(ptr[char]))
|
|
263
|
+
|
|
264
|
+
let allocated_args = storage.alloc[ptr[char]](command.len + 1) else:
|
|
265
|
+
fatal(c"process args storage exhausted")
|
|
266
|
+
|
|
267
|
+
let args_ptr = unsafe: allocated_args
|
|
268
|
+
|
|
269
|
+
var env_ptr: ptr[ptr[char]]? = null
|
|
270
|
+
var env_storage: ptr[ptr[char]]? = null
|
|
271
|
+
if env.len != 0:
|
|
272
|
+
let allocated = storage.alloc[ptr[char]](env.len + 1) else:
|
|
273
|
+
fatal(c"process env pointer storage exhausted")
|
|
274
|
+
|
|
275
|
+
let allocated_ptr = unsafe: allocated
|
|
276
|
+
env_ptr = allocated_ptr
|
|
277
|
+
env_storage = allocated_ptr
|
|
278
|
+
|
|
279
|
+
var index: ptr_uint = 0
|
|
280
|
+
while index < command.len:
|
|
281
|
+
let value = unsafe: read(command.data + index)
|
|
282
|
+
unsafe: read(args_ptr + index) = ptr[char]<-storage.to_cstr(value)
|
|
283
|
+
index += 1
|
|
284
|
+
|
|
285
|
+
unsafe: clear_pointer_slot(args_ptr + command.len)
|
|
286
|
+
|
|
287
|
+
if env.len != 0:
|
|
288
|
+
let allocated_ptr = env_storage else:
|
|
289
|
+
fatal(c"process env pointer storage missing")
|
|
290
|
+
|
|
291
|
+
let env_storage_ptr = unsafe: allocated_ptr
|
|
292
|
+
index = 0
|
|
293
|
+
while index < env.len:
|
|
294
|
+
let entry = unsafe: read(env.data + index)
|
|
295
|
+
unsafe: read(env_storage_ptr + index) = ptr[char]<-write_environment_value(ref_of(storage), entry)
|
|
296
|
+
index += 1
|
|
297
|
+
|
|
298
|
+
unsafe: clear_pointer_slot(env_storage_ptr + env.len)
|
|
299
|
+
|
|
300
|
+
let file = unsafe: cstr<-read(args_ptr)
|
|
301
|
+
var prepared_cwd: cstr? = null
|
|
302
|
+
match cwd:
|
|
303
|
+
Option.some as payload:
|
|
304
|
+
prepared_cwd = storage.to_cstr(payload.value)
|
|
305
|
+
Option.none:
|
|
306
|
+
pass
|
|
307
|
+
|
|
308
|
+
return Result[PreparedCommand, ProcessError].success(
|
|
309
|
+
value= PreparedCommand(storage = storage, file = file, args = args_ptr, env = env_ptr, cwd = prepared_cwd)
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
function take_process_error(raw: c.mt_process_error) -> ProcessError:
|
|
314
|
+
if raw.message_data == null and raw.message_len == 0:
|
|
315
|
+
return ProcessError(code = raw.code, message = string.String.from_str("process failed"))
|
|
316
|
+
|
|
317
|
+
return ProcessError(code = raw.code, message = take_owned_string(raw.message_data, raw.message_len))
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
function simple_process_error(message: str) -> ProcessError:
|
|
321
|
+
return ProcessError(code = -1, message = string.String.from_str(message))
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
function take_read_result(raw: c.mt_process_read_result) -> ReadResult:
|
|
325
|
+
return ReadResult(ready = raw.ready, closed = raw.closed, data = take_owned_string(raw.data, raw.len))
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
function take_wait_status(raw: c.mt_process_wait_result) -> ExitStatus:
|
|
329
|
+
return ExitStatus(exit_code = raw.exit_status, term_signal = raw.term_signal)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
function close_fd_quiet(fd: int) -> void:
|
|
333
|
+
if fd < 0:
|
|
334
|
+
return
|
|
335
|
+
|
|
336
|
+
var raw_error = zero[c.mt_process_error]
|
|
337
|
+
c.mt_process_close_fd(fd, raw_error)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
function close_fd_checked(fd: int) -> Result[bool, ProcessError]:
|
|
341
|
+
if fd < 0:
|
|
342
|
+
return Result[bool, ProcessError].success(value= true)
|
|
343
|
+
|
|
344
|
+
var raw_error = zero[c.mt_process_error]
|
|
345
|
+
let status = c.mt_process_close_fd(fd, raw_error)
|
|
346
|
+
if status != 0:
|
|
347
|
+
return Result[bool, ProcessError].failure(error= take_process_error(raw_error))
|
|
348
|
+
|
|
349
|
+
return Result[bool, ProcessError].success(value= true)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
function read_fd_internal(fd: int, timeout_ms: int) -> Result[ReadResult, ProcessError]:
|
|
353
|
+
if fd < 0:
|
|
354
|
+
return Result[ReadResult, ProcessError].failure(error= simple_process_error("process stream is closed"))
|
|
355
|
+
|
|
356
|
+
var raw_result = zero[c.mt_process_read_result]
|
|
357
|
+
var raw_error = zero[c.mt_process_error]
|
|
358
|
+
let status = c.mt_process_read_fd(fd, timeout_ms, raw_result, raw_error)
|
|
359
|
+
if status != 0:
|
|
360
|
+
return Result[ReadResult, ProcessError].failure(error= take_process_error(raw_error))
|
|
361
|
+
|
|
362
|
+
return Result[ReadResult, ProcessError].success(value= take_read_result(raw_result))
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
function write_fd_internal(fd: int, value: str) -> Result[ptr_uint, ProcessError]:
|
|
366
|
+
if fd < 0:
|
|
367
|
+
return Result[ptr_uint, ProcessError].failure(error= simple_process_error("process stream is closed"))
|
|
368
|
+
|
|
369
|
+
var data: const_ptr[char]? = null
|
|
370
|
+
if value.len != 0:
|
|
371
|
+
data = unsafe: const_ptr[char]<-value.data
|
|
372
|
+
|
|
373
|
+
var written: ptr_uint = 0
|
|
374
|
+
var raw_error = zero[c.mt_process_error]
|
|
375
|
+
let status = c.mt_process_write_fd(fd, data, value.len, written, raw_error)
|
|
376
|
+
if status != 0:
|
|
377
|
+
return Result[ptr_uint, ProcessError].failure(error= take_process_error(raw_error))
|
|
378
|
+
|
|
379
|
+
return Result[ptr_uint, ProcessError].success(value= written)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
function wait_internal(pid: int, non_blocking: bool) -> Result[Option[ExitStatus], ProcessError]:
|
|
383
|
+
if pid <= 0:
|
|
384
|
+
return Result[Option[ExitStatus], ProcessError].failure(error= simple_process_error("process pid is invalid"))
|
|
385
|
+
|
|
386
|
+
var raw_result = zero[c.mt_process_wait_result]
|
|
387
|
+
var raw_error = zero[c.mt_process_error]
|
|
388
|
+
var status = 0
|
|
389
|
+
if non_blocking:
|
|
390
|
+
status = c.mt_process_try_wait(pid, raw_result, raw_error)
|
|
391
|
+
else:
|
|
392
|
+
status = c.mt_process_wait(pid, raw_result, raw_error)
|
|
393
|
+
|
|
394
|
+
if status != 0:
|
|
395
|
+
return Result[Option[ExitStatus], ProcessError].failure(error= take_process_error(raw_error))
|
|
396
|
+
|
|
397
|
+
if not raw_result.ready:
|
|
398
|
+
return Result[Option[ExitStatus], ProcessError].success(value= Option[ExitStatus].none)
|
|
399
|
+
|
|
400
|
+
return Result[
|
|
401
|
+
Option[ExitStatus],
|
|
402
|
+
ProcessError
|
|
403
|
+
].success(value= Option[ExitStatus].some(value= take_wait_status(raw_result)))
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
function kill_internal(pid: int, signal: int) -> Result[bool, ProcessError]:
|
|
407
|
+
if pid <= 0:
|
|
408
|
+
return Result[bool, ProcessError].failure(error= simple_process_error("process pid is invalid"))
|
|
409
|
+
|
|
410
|
+
var raw_error = zero[c.mt_process_error]
|
|
411
|
+
let status = c.mt_process_kill(pid, signal, raw_error)
|
|
412
|
+
if status != 0:
|
|
413
|
+
return Result[bool, ProcessError].failure(error= take_process_error(raw_error))
|
|
414
|
+
|
|
415
|
+
return Result[bool, ProcessError].success(value= true)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
function resize_pty_internal(fd: int, columns: int, rows: int) -> Result[bool, ProcessError]:
|
|
419
|
+
if fd < 0:
|
|
420
|
+
return Result[bool, ProcessError].failure(error= simple_process_error("process stream is closed"))
|
|
421
|
+
|
|
422
|
+
var raw_error = zero[c.mt_process_error]
|
|
423
|
+
let status = c.mt_process_pty_resize(fd, columns, rows, raw_error)
|
|
424
|
+
if status != 0:
|
|
425
|
+
return Result[bool, ProcessError].failure(error= take_process_error(raw_error))
|
|
426
|
+
|
|
427
|
+
return Result[bool, ProcessError].success(value= true)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
function spawn_internal(
|
|
431
|
+
command: span[str],
|
|
432
|
+
cwd: Option[str],
|
|
433
|
+
env: span[EnvironmentEntry]
|
|
434
|
+
) -> Result[ChildProcess, ProcessError]:
|
|
435
|
+
let prepared_result = prepare_command(command, cwd, env)
|
|
436
|
+
match prepared_result:
|
|
437
|
+
Result.failure as payload:
|
|
438
|
+
return Result[ChildProcess, ProcessError].failure(error= payload.error)
|
|
439
|
+
Result.success as payload:
|
|
440
|
+
var prepared = payload.value
|
|
441
|
+
defer prepared.release()
|
|
442
|
+
|
|
443
|
+
var raw_handle = zero[c.mt_process_spawn_handle]
|
|
444
|
+
var raw_error = zero[c.mt_process_error]
|
|
445
|
+
let status = c.mt_process_spawn_interactive(
|
|
446
|
+
prepared.file,
|
|
447
|
+
prepared.args,
|
|
448
|
+
prepared.env,
|
|
449
|
+
prepared.cwd,
|
|
450
|
+
raw_handle,
|
|
451
|
+
raw_error
|
|
452
|
+
)
|
|
453
|
+
if status != 0:
|
|
454
|
+
return Result[ChildProcess, ProcessError].failure(error= take_process_error(raw_error))
|
|
455
|
+
|
|
456
|
+
return Result[ChildProcess, ProcessError].success(
|
|
457
|
+
value= ChildProcess(
|
|
458
|
+
pid = raw_handle.pid,
|
|
459
|
+
stdin_fd = raw_handle.stdin_fd,
|
|
460
|
+
stdout_fd = raw_handle.stdout_fd,
|
|
461
|
+
stderr_fd = raw_handle.stderr_fd
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
function spawn_pty_internal(
|
|
467
|
+
command: span[str],
|
|
468
|
+
cwd: Option[str],
|
|
469
|
+
env: span[EnvironmentEntry],
|
|
470
|
+
columns: int,
|
|
471
|
+
rows: int
|
|
472
|
+
) -> Result[PtyProcess, ProcessError]:
|
|
473
|
+
if columns <= 0 or rows <= 0:
|
|
474
|
+
return Result[PtyProcess, ProcessError].failure(error= simple_process_error("pty size must be positive"))
|
|
475
|
+
|
|
476
|
+
let prepared_result = prepare_command(command, cwd, env)
|
|
477
|
+
match prepared_result:
|
|
478
|
+
Result.failure as payload:
|
|
479
|
+
return Result[PtyProcess, ProcessError].failure(error= payload.error)
|
|
480
|
+
Result.success as payload:
|
|
481
|
+
var prepared = payload.value
|
|
482
|
+
defer prepared.release()
|
|
483
|
+
|
|
484
|
+
var raw_handle = zero[c.mt_process_pty_handle]
|
|
485
|
+
var raw_error = zero[c.mt_process_error]
|
|
486
|
+
let status = c.mt_process_spawn_pty(
|
|
487
|
+
prepared.file,
|
|
488
|
+
prepared.args,
|
|
489
|
+
prepared.env,
|
|
490
|
+
prepared.cwd,
|
|
491
|
+
columns,
|
|
492
|
+
rows,
|
|
493
|
+
raw_handle,
|
|
494
|
+
raw_error
|
|
495
|
+
)
|
|
496
|
+
if status != 0:
|
|
497
|
+
return Result[PtyProcess, ProcessError].failure(error= take_process_error(raw_error))
|
|
498
|
+
|
|
499
|
+
return Result[PtyProcess, ProcessError].success(value= PtyProcess(
|
|
500
|
+
pid = raw_handle.pid,
|
|
501
|
+
master_fd = raw_handle.master_fd
|
|
502
|
+
))
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
function capture_internal(
|
|
506
|
+
command: span[str],
|
|
507
|
+
cwd: Option[str],
|
|
508
|
+
env: span[EnvironmentEntry]
|
|
509
|
+
) -> Result[CaptureResult, ProcessError]:
|
|
510
|
+
let prepared_result = prepare_command(command, cwd, env)
|
|
511
|
+
match prepared_result:
|
|
512
|
+
Result.failure as payload:
|
|
513
|
+
return Result[CaptureResult, ProcessError].failure(error= payload.error)
|
|
514
|
+
Result.success as payload:
|
|
515
|
+
var prepared = payload.value
|
|
516
|
+
defer prepared.release()
|
|
517
|
+
|
|
518
|
+
var raw_result = zero[c.mt_process_capture_result]
|
|
519
|
+
var raw_error = zero[c.mt_process_error]
|
|
520
|
+
let status_code = c.mt_process_capture(
|
|
521
|
+
prepared.file,
|
|
522
|
+
prepared.args,
|
|
523
|
+
prepared.env,
|
|
524
|
+
prepared.cwd,
|
|
525
|
+
raw_result,
|
|
526
|
+
raw_error
|
|
527
|
+
)
|
|
528
|
+
if status_code != 0:
|
|
529
|
+
return Result[CaptureResult, ProcessError].failure(error= take_process_error(raw_error))
|
|
530
|
+
|
|
531
|
+
return Result[CaptureResult, ProcessError].success(
|
|
532
|
+
value= CaptureResult(
|
|
533
|
+
stdout = take_owned_string(raw_result.stdout_data, raw_result.stdout_len),
|
|
534
|
+
stderr = take_owned_string(raw_result.stderr_data, raw_result.stderr_len),
|
|
535
|
+
status = ExitStatus(exit_code = raw_result.exit_status, term_signal = raw_result.term_signal)
|
|
536
|
+
)
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
function spawn_detached_internal(
|
|
541
|
+
command: span[str],
|
|
542
|
+
cwd: Option[str],
|
|
543
|
+
env: span[EnvironmentEntry]
|
|
544
|
+
) -> Result[int, ProcessError]:
|
|
545
|
+
let prepared_result = prepare_command(command, cwd, env)
|
|
546
|
+
match prepared_result:
|
|
547
|
+
Result.failure as payload:
|
|
548
|
+
return Result[int, ProcessError].failure(error= payload.error)
|
|
549
|
+
Result.success as payload:
|
|
550
|
+
var prepared = payload.value
|
|
551
|
+
defer prepared.release()
|
|
552
|
+
|
|
553
|
+
var pid: int = 0
|
|
554
|
+
var raw_error = zero[c.mt_process_error]
|
|
555
|
+
let status_code = c.mt_process_spawn_detached(
|
|
556
|
+
prepared.file,
|
|
557
|
+
prepared.args,
|
|
558
|
+
prepared.env,
|
|
559
|
+
prepared.cwd,
|
|
560
|
+
pid,
|
|
561
|
+
raw_error
|
|
562
|
+
)
|
|
563
|
+
if status_code != 0:
|
|
564
|
+
return Result[int, ProcessError].failure(error= take_process_error(raw_error))
|
|
565
|
+
|
|
566
|
+
return Result[int, ProcessError].success(value= pid)
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
extending ExitStatus:
|
|
570
|
+
public function success() -> bool:
|
|
571
|
+
return this.exit_code == 0 and this.term_signal == 0
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
public function normalized_code() -> int:
|
|
575
|
+
if this.term_signal != 0:
|
|
576
|
+
return 128 + this.term_signal
|
|
577
|
+
|
|
578
|
+
return int<-this.exit_code
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
extending CaptureResult:
|
|
582
|
+
public function success() -> bool:
|
|
583
|
+
return this.status.success()
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
public function stdout_text() -> Option[str]:
|
|
587
|
+
return safe_text_view(this.stdout)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
public function stderr_text() -> Option[str]:
|
|
591
|
+
return safe_text_view(this.stderr)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
public editable function release() -> void:
|
|
595
|
+
this.stdout.release()
|
|
596
|
+
this.stderr.release()
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
extending ReadResult:
|
|
600
|
+
public function text() -> Option[str]:
|
|
601
|
+
return safe_text_view(this.data)
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
public function has_data() -> bool:
|
|
605
|
+
return this.data.len != 0
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
public editable function release() -> void:
|
|
609
|
+
this.data.release()
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
extending ChildProcess:
|
|
613
|
+
public function read_stdout(timeout_ms: int) -> Result[ReadResult, ProcessError]:
|
|
614
|
+
return read_fd_internal(this.stdout_fd, timeout_ms)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
public function read_stderr(timeout_ms: int) -> Result[ReadResult, ProcessError]:
|
|
618
|
+
return read_fd_internal(this.stderr_fd, timeout_ms)
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
public function write_stdin(value: str) -> Result[ptr_uint, ProcessError]:
|
|
622
|
+
return write_fd_internal(this.stdin_fd, value)
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
public editable function close_stdin() -> Result[bool, ProcessError]:
|
|
626
|
+
match close_fd_checked(this.stdin_fd):
|
|
627
|
+
Result.failure as payload:
|
|
628
|
+
return Result[bool, ProcessError].failure(error= payload.error)
|
|
629
|
+
Result.success as payload:
|
|
630
|
+
this.stdin_fd = -1
|
|
631
|
+
return Result[bool, ProcessError].success(value= payload.value)
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
public editable function close_stdout() -> Result[bool, ProcessError]:
|
|
635
|
+
match close_fd_checked(this.stdout_fd):
|
|
636
|
+
Result.failure as payload:
|
|
637
|
+
return Result[bool, ProcessError].failure(error= payload.error)
|
|
638
|
+
Result.success as payload:
|
|
639
|
+
this.stdout_fd = -1
|
|
640
|
+
return Result[bool, ProcessError].success(value= payload.value)
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
public editable function close_stderr() -> Result[bool, ProcessError]:
|
|
644
|
+
match close_fd_checked(this.stderr_fd):
|
|
645
|
+
Result.failure as payload:
|
|
646
|
+
return Result[bool, ProcessError].failure(error= payload.error)
|
|
647
|
+
Result.success as payload:
|
|
648
|
+
this.stderr_fd = -1
|
|
649
|
+
return Result[bool, ProcessError].success(value= payload.value)
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
public editable function wait() -> Result[ExitStatus, ProcessError]:
|
|
653
|
+
let wait_result = wait_internal(this.pid, false)
|
|
654
|
+
match wait_result:
|
|
655
|
+
Result.failure as payload:
|
|
656
|
+
return Result[ExitStatus, ProcessError].failure(error= payload.error)
|
|
657
|
+
Result.success as payload:
|
|
658
|
+
match payload.value:
|
|
659
|
+
Option.some as status_payload:
|
|
660
|
+
this.pid = 0
|
|
661
|
+
return Result[ExitStatus, ProcessError].success(value= status_payload.value)
|
|
662
|
+
Option.none:
|
|
663
|
+
return Result[
|
|
664
|
+
ExitStatus,
|
|
665
|
+
ProcessError
|
|
666
|
+
].failure(error= simple_process_error("process wait returned no status"))
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
public editable function try_wait() -> Result[Option[ExitStatus], ProcessError]:
|
|
670
|
+
let wait_result = wait_internal(this.pid, true)
|
|
671
|
+
match wait_result:
|
|
672
|
+
Result.failure as payload:
|
|
673
|
+
return Result[Option[ExitStatus], ProcessError].failure(error= payload.error)
|
|
674
|
+
Result.success as payload:
|
|
675
|
+
match payload.value:
|
|
676
|
+
Option.some as status_payload:
|
|
677
|
+
this.pid = 0
|
|
678
|
+
return Result[
|
|
679
|
+
Option[ExitStatus],
|
|
680
|
+
ProcessError
|
|
681
|
+
].success(value= Option[ExitStatus].some(value= status_payload.value))
|
|
682
|
+
Option.none:
|
|
683
|
+
return Result[Option[ExitStatus], ProcessError].success(value= Option[ExitStatus].none)
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
public function kill(signal: int) -> Result[bool, ProcessError]:
|
|
687
|
+
return kill_internal(this.pid, signal)
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
public editable function release() -> void:
|
|
691
|
+
close_fd_quiet(this.stdin_fd)
|
|
692
|
+
close_fd_quiet(this.stdout_fd)
|
|
693
|
+
close_fd_quiet(this.stderr_fd)
|
|
694
|
+
this.stdin_fd = -1
|
|
695
|
+
this.stdout_fd = -1
|
|
696
|
+
this.stderr_fd = -1
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
extending PtyProcess:
|
|
700
|
+
public function read(timeout_ms: int) -> Result[ReadResult, ProcessError]:
|
|
701
|
+
return read_fd_internal(this.master_fd, timeout_ms)
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
public function write(value: str) -> Result[ptr_uint, ProcessError]:
|
|
705
|
+
return write_fd_internal(this.master_fd, value)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
public function resize(columns: int, rows: int) -> Result[bool, ProcessError]:
|
|
709
|
+
return resize_pty_internal(this.master_fd, columns, rows)
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
public editable function close() -> Result[bool, ProcessError]:
|
|
713
|
+
match close_fd_checked(this.master_fd):
|
|
714
|
+
Result.failure as payload:
|
|
715
|
+
return Result[bool, ProcessError].failure(error= payload.error)
|
|
716
|
+
Result.success as payload:
|
|
717
|
+
this.master_fd = -1
|
|
718
|
+
return Result[bool, ProcessError].success(value= payload.value)
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
public editable function wait() -> Result[ExitStatus, ProcessError]:
|
|
722
|
+
let wait_result = wait_internal(this.pid, false)
|
|
723
|
+
match wait_result:
|
|
724
|
+
Result.failure as payload:
|
|
725
|
+
return Result[ExitStatus, ProcessError].failure(error= payload.error)
|
|
726
|
+
Result.success as payload:
|
|
727
|
+
match payload.value:
|
|
728
|
+
Option.some as status_payload:
|
|
729
|
+
this.pid = 0
|
|
730
|
+
return Result[ExitStatus, ProcessError].success(value= status_payload.value)
|
|
731
|
+
Option.none:
|
|
732
|
+
return Result[
|
|
733
|
+
ExitStatus,
|
|
734
|
+
ProcessError
|
|
735
|
+
].failure(error= simple_process_error("process wait returned no status"))
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
public editable function try_wait() -> Result[Option[ExitStatus], ProcessError]:
|
|
739
|
+
let wait_result = wait_internal(this.pid, true)
|
|
740
|
+
match wait_result:
|
|
741
|
+
Result.failure as payload:
|
|
742
|
+
return Result[Option[ExitStatus], ProcessError].failure(error= payload.error)
|
|
743
|
+
Result.success as payload:
|
|
744
|
+
match payload.value:
|
|
745
|
+
Option.some as status_payload:
|
|
746
|
+
this.pid = 0
|
|
747
|
+
return Result[
|
|
748
|
+
Option[ExitStatus],
|
|
749
|
+
ProcessError
|
|
750
|
+
].success(value= Option[ExitStatus].some(value= status_payload.value))
|
|
751
|
+
Option.none:
|
|
752
|
+
return Result[Option[ExitStatus], ProcessError].success(value= Option[ExitStatus].none)
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
public function kill(signal: int) -> Result[bool, ProcessError]:
|
|
756
|
+
return kill_internal(this.pid, signal)
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
public editable function release() -> void:
|
|
760
|
+
close_fd_quiet(this.master_fd)
|
|
761
|
+
this.master_fd = -1
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
extending ProcessError:
|
|
765
|
+
public editable function release() -> void:
|
|
766
|
+
this.message.release()
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
extending PreparedCommand:
|
|
770
|
+
editable function release() -> void:
|
|
771
|
+
this.storage.release()
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
public function capture(command: span[str]) -> Result[CaptureResult, ProcessError]:
|
|
775
|
+
return capture_internal(command, Option[str].none, empty_environment())
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
public function capture_in(command: span[str], cwd: str) -> Result[CaptureResult, ProcessError]:
|
|
779
|
+
return capture_internal(command, Option[str].some(value= cwd), empty_environment())
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
public function capture_with_env(
|
|
783
|
+
command: span[str],
|
|
784
|
+
cwd: Option[str],
|
|
785
|
+
env: span[EnvironmentEntry]
|
|
786
|
+
) -> Result[CaptureResult, ProcessError]:
|
|
787
|
+
return capture_internal(command, cwd, env)
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
public function spawn(command: span[str]) -> Result[ChildProcess, ProcessError]:
|
|
791
|
+
return spawn_internal(command, Option[str].none, empty_environment())
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
public function spawn_in(command: span[str], cwd: str) -> Result[ChildProcess, ProcessError]:
|
|
795
|
+
return spawn_internal(command, Option[str].some(value= cwd), empty_environment())
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
public function spawn_with_env(
|
|
799
|
+
command: span[str],
|
|
800
|
+
cwd: Option[str],
|
|
801
|
+
env: span[EnvironmentEntry]
|
|
802
|
+
) -> Result[ChildProcess, ProcessError]:
|
|
803
|
+
return spawn_internal(command, cwd, env)
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
public function spawn_pty(command: span[str], columns: int, rows: int) -> Result[PtyProcess, ProcessError]:
|
|
807
|
+
return spawn_pty_internal(command, Option[str].none, empty_environment(), columns, rows)
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
public function spawn_pty_in(command: span[str], cwd: str, columns: int, rows: int) -> Result[PtyProcess, ProcessError]:
|
|
811
|
+
return spawn_pty_internal(command, Option[str].some(value= cwd), empty_environment(), columns, rows)
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
public function spawn_pty_with_env(
|
|
815
|
+
command: span[str],
|
|
816
|
+
cwd: Option[str],
|
|
817
|
+
env: span[EnvironmentEntry],
|
|
818
|
+
columns: int,
|
|
819
|
+
rows: int
|
|
820
|
+
) -> Result[PtyProcess, ProcessError]:
|
|
821
|
+
return spawn_pty_internal(command, cwd, env, columns, rows)
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
public function spawn_detached(command: span[str]) -> Result[int, ProcessError]:
|
|
825
|
+
return spawn_detached_internal(command, Option[str].none, empty_environment())
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
public function spawn_detached_in(command: span[str], cwd: str) -> Result[int, ProcessError]:
|
|
829
|
+
return spawn_detached_internal(command, Option[str].some(value= cwd), empty_environment())
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
public function spawn_detached_with_env(
|
|
833
|
+
command: span[str],
|
|
834
|
+
cwd: Option[str],
|
|
835
|
+
env: span[EnvironmentEntry]
|
|
836
|
+
) -> Result[int, ProcessError]:
|
|
837
|
+
return spawn_detached_internal(command, cwd, env)
|