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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
module os
#const $child_process = require('child_process')
// new_process - create a new process descriptor
// NB: new does NOT start the new process.
// That is done because you may want to customize it first,
// by calling different set_ methods on it.
// In order to start it, call p.run() or p.wait()
pub fn new_process(filename string) &Process {
return &Process{
filename: filename
stdio_fd: [-1, -1, -1]!
}
}
fn (mut p Process) spawn_internal() {
#p.val.pid = $child_process.spawn(
#p.val.filename+'',
#p.val.args.arr.map((x) => x.valueOf() + ''),
#{
#env: (p.val.env_is_custom ? p.val.env : $process.env),
#})
#p.val.pid.on('error', function (err) { builtin.panic('Failed to start subprocess') })
p.status = .running
// todo(playX): stderr,stdin
if p.use_stdio_ctl {
#p.val.pid.stdout.pipe(process.stdout)
#p.val.pid.stdin.pipe(process.stdin)
#p.val.pid.stderr.pipe(process.stderr)
}
}
pub fn (mut p Process) run() {
if p.status != .not_started {
return
}
p.spawn_internal()
return
}
pub fn (mut p Process) signal_kill() {
if p.status !in [.running, .stopped] {
return
}
#p.val.pid.kill('SIGKILL');
p.status = .aborted
}
pub fn (mut p Process) signal_stop() {
if p.status !in [.running, .stopped] {
return
}
#p.val.pid.kill('SIGSTOP');
p.status = .aborted
}
pub fn (mut p Process) signal_continue() {
if p.status != .stopped {
return
}
#p.val.pid.kill('SIGCONT');
p.status = .running
return
}
pub fn (mut p Process) wait() {
if p.status == .not_started {
p.spawn_internal()
}
if p.status !in [.running, .stopped] {
return
}
p.wait_internal()
return
}
fn (mut p Process) wait_internal() {
#p.val.pid.on('exit', function (code) { console.log(code) })
}
pub fn (mut p Process) set_redirect_stdio() {
p.use_stdio_ctl = true
return
}
pub fn (mut p Process) stdin_write(s string) {
p.check_redirection_call('stdin_write')
#p.val.pid.stdin.write(s)
}
// todo(playX): probably does not work
// will read from stdout pipe, will only return when EOF (end of file) or data
// means this will block unless there is data
pub fn (mut p Process) stdout_slurp() string {
p.check_redirection_call('stdout_slurp')
mut res := ''
#p.val.pid.stdout.on('data', function (data) { res = new builtin.string(data) })
return res
}
// _check_redirection_call - should be called just by stdxxx methods
fn (mut p Process) check_redirection_call(fn_name string) {
if !p.use_stdio_ctl {
panic('Call p.set_redirect_stdio() before calling p.$fn_name')
}
if p.status == .not_started {
panic('Call p.${fn_name}() after you have called p.run()')
}
}
|