This works in Nim 1.2.6 but not in 1.3.5 and it behaves in an apparently illogical way. It's a simplified standalone example from Pakku, the actual option to makepkg causing the problem is --printsrcinfo but --version does the same. Perplexingly, -V does work. And running just the exec part works, the short top piece of code below. findmnt ---version works, and that has the same length command. The intention is to run a shell command and capture the info that would usually be printed to stdout. Does anyone have any ideas how to get around this?
import posix
- proc execResult*(args: varargs[string]): int =
- let cexec = allocCStringArray(args) let code = execvp(cexec[0], cexec) deallocCStringArray(cexec) code
let retval = execResult("makepkg", "--version")
echo retval
import posix, sequtils, strutils, sugar
- proc execResult(args: varargs[string]): int =
- let cexec = allocCStringArray(args) let code = execvp(cexec[0], cexec) deallocCStringArray(cexec) code
- proc forkWaitInternal(call: () -> int, beforeWait: () -> void): int =
- let pid = fork()
- if pid == 0:
- quit(call())
- else:
- beforeWait() var status: cint = 1 discard waitpid(pid, status, 0)
- if WIFEXITED(status):
- return WEXITSTATUS(status)
- else:
- discard kill(getpid(), status) return 1
- proc forkWaitRedirect(call: () -> int): tuple[output: seq[string], code: int] =
- var fd: array[2, cint] discard pipe(fd) var data = newSeqchar
- let code = forkWaitInternal(() => (block:
- discard close(fd[0]) discard close(1) discard dup(fd[1]) discard close(fd[1]) discard close(0) discard open("/dev/null") discard close(2) discard open("/dev/null") call()), () => (block: discard close(fd[1]) var buffer: array[80, char]
- while true:
- let count = read(fd[0], addr(buffer[0]), buffer.len)
- if count <= 0:
- break
data &= buffer[0 .. count - 1]
discard close(fd[0])))
var output = newStringOfCap(data.len)
- for c in data:
- output &= c
- let lines = if output.len == 0:
- @[]
- elif output.len > 0 and $output[^1] == "n":
- output[0 .. ^2].split("n")
- else:
- output.split("n")
(lines, code)
- proc obtainSrcInfo(): string =
- let (output, code) = forkWaitRedirect(() => (block:
- execResult("makepkg", "--version"))) # doesn't work, error code 3: "user specified an invalid option"
execResult("makepkg", "-V"))) # this works
execResult("findmnt", "--version"))) # this works too
- if code == 0:
- echo "code = ", code output.foldl(a & b & "n", "")
- else:
- echo "else, code = ", code ""
let resultString = obtainSrcInfo()
echo resultString