v/examples/process/process_stdin_trick.v

75 lines
1.8 KiB
V

module main
import os
// this is a example script to show you stdin can be used and keep a process open
fn exec(cmd string) (string, int) {
mut cmd2 := cmd
mut out := ''
mut line := ''
mut rc := 0
mut p := os.new_process('/bin/bash')
// there are methods missing to know if stderr/stdout has data as such its better to redirect bot on same FD
// not so nice trick to run bash in bash and redirect stderr, maybe someone has a better solution
p.set_args(['-c', 'bash 2>&1'])
p.set_redirect_stdio()
p.run()
p.stdin_write('$cmd2 && echo **OK**')
os.fd_close(p.stdio_fd[0]) // important: close stdin so cmd can end by itself
for p.is_alive() {
line = p.stdout_read()
println(line)
// line_err = p.stderr_read() //IF WE CALL STDERR_READ will block
// we need a mechanism which allows us to check if stderr/stdout has data or it should never block
// is not a good way, need to use a string buffer, is slow like this
out += line
if line.ends_with('**OK**\n') {
out = out[0..(out.len - 7)]
break
}
}
// println("read from stdout, should not block")
// is not really needed but good test to see behaviour
out += p.stdout_read()
println('read done')
println(p.stderr_read())
p.close()
p.wait()
if p.code > 0 {
rc = 1
println('ERROR:')
println(cmd2)
print(out)
}
return out, rc
}
fn main() {
mut out := ''
mut rc := 0
// find files from /tmp excluding files unlistable by current user
out, rc = exec("find /tmp/ -user \$UID; echo '******'")
println(out)
assert out.ends_with('******\n')
out, rc = exec('echo to stdout')
assert out.contains('to stdout')
out, rc = exec('echo to stderr 1>&2')
assert out.contains('to stderr')
out, rc = exec('ls /sssss')
assert rc > 0 // THIS STILL GIVES AN ERROR !
println('test ok stderr & stdout is indeed redirected')
}