Reputation: 477
I am attempting to write/print text to the screen from a Go program launched from another console/terminal application--a "door" program that launches from an old-school Bulletin Board System (BBS).
The BBS itself runs over a telnet connection, localhost:2323. And when launching my program, the BBS automatically adds the correct socket handle as an argument, which I can then read using Flag (it's an integer, like 236).
Obviously, in Linux, I'd just use fmt.Println("Hello World!")
using os.Stdout... But on Windows, I need to somehow pipe/redirect the Go program's output to the provided socket.
Here's the function I started with:
func writeOut(fd int, buf []byte) bool {
for len(buf) > 0 {
n, err := syscall.Write(syscall.Handle(fd), buf)
if err != nil {
fmt.Println(err)
return false
}
buf = buf[n:]
}
return true
}
called from:
writeOut(socketInt, []byte("Writing to Windows socket..."))
The error returned is: The parameter is incorrect
What am I doing wrong, and how would this be accomplished in Go?
Upvotes: 2
Views: 640
Reputation: 85286
You can't arbitrarily pass file or socket handles to another process that isn't inheriting them from your process in the first place. Each process has its own unique set of handles. In POSIX inheriting socket handles is possible (albeit not recommended) but in Windows they simply cannot be inherited (see Are TCP SOCKET handles inheritable?).
You can redirect stdout
to a TCP socket when calling CreateProcess
though, so that when invoked, your program can indeed fmt.Println
to stdout
and the output would go straight to the socket:
func serveDoor(conn *net.TCPConn, name string, args ...string) {
defer conn.Close()
cmd := exec.Command(name, args...)
cmd.Stdin = conn
cmd.Stdout = conn
cmd.Stderr = conn
err := cmd.Run()
fmt.Println("door finished:", err)
}
Another solution is to use a pipe and pump it to the socket.
Upvotes: 2