Robbie
Robbie

Reputation: 477

Write to existing tcp socket over telnet/ssh in Go on Windows

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

Answers (1)

rustyx
rustyx

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)
}

(full gist)

Another solution is to use a pipe and pump it to the socket.

Upvotes: 2

Related Questions