Skip to content

Instantly share code, notes, and snippets.

@Tetralux
Last active September 29, 2022 06:32
Show Gist options
  • Save Tetralux/c7d1d0562786675e8c73bc7f3bfdff80 to your computer and use it in GitHub Desktop.
Save Tetralux/c7d1d0562786675e8c73bc7f3bfdff80 to your computer and use it in GitHub Desktop.
Example of how to bind and use popen from libc
package process
import "core:c"
import "core:c/libc"
import "core:strings"
when ODIN_OS == .Windows {
foreign import libc_obj "system:libucrt.lib"
POPEN_NAME :: "_popen"
PCLOSE_NAME :: "_pclose"
} else when ODIN_OS == .Darwin {
foreign import libc_obj "system:System.framework"
POPEN_NAME :: "popen"
PCLOSE_NAME :: "pclose"
} else {
foreign import libc_obj "system:c"
POPEN_NAME :: "popen"
PCLOSE_NAME :: "pclose"
}
@(default_calling_convention="c")
foreign libc_obj {
@(link_name=POPEN_NAME) popen :: proc(command: cstring, typ: cstring) -> ^libc.FILE ---
@(link_name=PCLOSE_NAME) pclose :: proc(stream: ^libc.FILE) -> c.int ---
}
Process :: distinct ^libc.FILE
start :: proc(cmd: string) -> (p: Process, ok: bool) {
cmd := strings.clone_to_cstring(cmd)
defer delete(cmd)
fd := popen(cmd, "rw")
if fd == nil do return
return Process(fd), true
}
wait :: proc(p: Process) {
pclose(cast(^libc.FILE) p) // NOTE: waits for the process to quit, and then frees it
}
// Write to the process' stdin.
write :: proc(p: Process, buf: []byte) -> (wrote: int, ok: bool) {
fd := cast(^libc.FILE) p
for wrote < len(buf) {
n := libc.fwrite(raw_data(buf), 1, c.size_t(len(buf)), fd)
if n == 0 {
ok = libc.ferror(fd) == 0
if !ok do libc.clearerr(fd)
return
}
wrote += int(n)
}
libc.fflush(fd) // NOTE: libc buffers the stdin/stdout of the process
ok = true
return
}
// Read from the process' stdout.
read :: proc(p: Process, dst: []byte) -> (read: int, ok: bool) {
fd := cast(^libc.FILE) p
n := libc.fread(raw_data(dst), 1, c.size_t(len(dst)), fd)
ok = libc.ferror(fd) == 0
if !ok do libc.clearerr(fd)
return int(n), ok
}
@bq-wrongway
Copy link

Hey, i am the person that asked this question on discord, sadly i dont grasp how i should use this to achieve what i want.
For example reading stdout, i need to pass a process and byte array to the read function, but i dont know which process.

SO when i try to execute libc.system("ls"), that i get feedback of what exactly happend, but passing that wont work since its of type int.

I hope my question is not bothering you, i am just trying to make sense of how to use code that you provided.

Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment