
header "sys" as sys

use utils
#if OS == win
use fs
#end

// execute command and return exit-code
+ fn exec(cmd: String, stream_output: bool (false)) (i32, String) {

    #if OS == win
    // Change current directory if in WSL
    // Otherwise it prints a warning on every exec
    let cwd = fs:cwd()
    let revert_cwd = false
    if cwd.starts_with("\\\\") {
        revert_cwd = true
        fs:chdir("C:/")
    }
    #end

    cmd += " 2>&1"
    let buf = utils:ByteBuffer.new(1024)
    let cstr = @stack([u8 x 1024]).@cast(cstring)
    let pipe = sys:popen(cmd.data_cstring, "r".data_cstring)
    if !isset(pipe) : return 1, "Exec failed to open process"

    while sys:fgets(cstr, 1024, pipe) != null {
        let len = cstr.length()
        buf.append_from_ptr(cstr, len)
        if stream_output : print(cstr)
    }

    let exit_code : i32 = 0
    let status = sys:pclose(pipe)
    if status != -1 {
        exit_code = WEXITSTATUS(status)
    }

    #if OS == win
    if revert_cwd : fs:chdir(cwd)
    #end

    return exit_code, buf.to_string()
}

fn WEXITSTATUS(status: i32) i32 {
    #if OS == win
    return status
    #else
    return (status & 0xff00) >> 8
    #end
}
