creack / pty

PTY interface for Go
https://pkg.go.dev/github.com/creack/pty?tab=doc
MIT License
1.65k stars 235 forks source link

Support Windows through `conpty` #95

Open hinshun opened 4 years ago

hinshun commented 4 years ago

Windows 10 gained support for psuedo-terminals with conpty: https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/

Prior art:

Would you be open to a PR?

creack commented 4 years ago

Having windows support would be great.

PRs are welcome indeed :)

On Thu, Apr 30, 2020 at 1:29 AM Edgar Lee notifications@github.com wrote:

Windows 10 gained support for psuedo-terminals with conpty: https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/

Prior art:

Would you be open to a PR?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/creack/pty/issues/95, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAD7LZNURJEB7ZAQFBT77DLRPEEDXANCNFSM4MVF3YSA .

-- --

Guillaume J. Charmes Software Engineer https://blog.charmes.net [image: Guillaume J. Charmes on about.me] https://blog.charmes.net

prabirshrestha commented 4 years ago

Another option would be to use go-winpty but is based of winpty.dll.

You can also look at the source of portable-pty from rust that supports both winpty and conpty.

virtuald commented 4 years ago

I noted in #50 that https://github.com/containerd/console has a console implementation for Windows. There's quite a bit of overlap with this library -- so it might be worth borrowing from that if someone were to open a PR.

liuhaowen478 commented 3 years ago

Any update on this? Would be so great to see this happen

mardukbp commented 3 years ago

ActiveState implemented a Go library for conpty: termtest/conpty

creack commented 3 years ago

@mardukbp unfortunatelly termtest/conpty is based on CGO, which is not an option here as it would be a breaking change. We could consider it for a v2 though.

@virtuald This looks interesting indeed, but as I have 0 experience with windows, I have no idea what's going on there.. If someone want to create a PR, I'd be happy to bring it in, but I don't think I'll have time to do it myself anytime soon.

@liuhaowen478 We are looking for motived people to contribute :)

mardukbp commented 3 years ago

@creack How do you know that termtest/conpty is based on CGO? As far as I can tell, it uses the syscall and windows go packages. I could not find any reference to cgo in the code.

creack commented 3 years ago

As I have no experience with windows, I might be wrong and I didn't test it, but I saw this: https://github.com/ActiveState/termtest/blob/master/conpty/syscall_windows.go#L16

AFAIK, loading a plugin in go requires cgo (golang/go#19569)

AlbinoDrought commented 3 years ago

For what it's worth, here's what I get on a Windows machine:

User@Desktop MINGW64 ~/go/src
$ CGO_ENABLED=0 go get github.com/ActiveState/termtest

User@Desktop MINGW64 ~/go/src
$ cd github.com/ActiveState/termtest/conpty/cmd/example

User@Desktop MINGW64 ~/go/src/github.com/ActiveState/termtest/conpty/cmd/example (master)
$ CGO_ENABLED=0 go build

User@Desktop MINGW64 ~/go/src/github.com/ActiveState/termtest/conpty/cmd/example (master)
$ ./example.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\Users\User\Downloads> echo "hello world"
hello world
PS C:\Users\User\Downloads>
exit code was: 0
mardukbp commented 3 years ago

According to the Go Wiki loading a DLL with syscall does not require cgo.

AFAIK, loading a plugin in go requires cgo (golang/go#19569)

Yes, but termtest/conpty does not use go plugins.

I think this library is good to go! 😉

ghost commented 3 years ago

Hi @creack , I have opened a pull request for windows conpty support (#109 ), but as noted as known issues there, I probably need some guidance to solve these issues since I am not a windows expert, any idea?

creack commented 3 years ago

@jeffreystoke I'll take a look this week, thanks for the pr!

imbytecat commented 2 years ago

Has there been any progress on the ConPTY support for Windows so far? I noticed that this PR is still not merged.

creack commented 2 years ago

Not yet. concerns about breaking change and overall usability issue. I haven't yet been able to get this to work on my windows machine.

photostorm commented 2 years ago

I think we fixed a lot of usability issues. I have tested it with powershell.

var f pty.Pty
var err error

f, err = pty.Start(exec.Command("powershell"))
if err != nil {
    return nil, err
}
jherman commented 2 years ago

@photostorm How did you getting it working? I have the following code:

func main() {
    var f pty.Pty
    var err error

    f, err = pty.Start(exec.Command("cmd"))
    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    h := f.Fd()

    oldState, err := term.MakeRaw(int(h))
    if err != nil {
        panic(err)
    }
    defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.

    go func() { _, _ = io.Copy(f, os.Stdin) }()
    _, _ = io.Copy(os.Stdout, f)
}

output:

panic: The handle is invalid.

goroutine 1 [running]:
main.main()
        C:/repos/work/github.com/jeffreystoke/pty/test/test.go:69 +0x1eb
exit status 2

I can't seem to get a proper windows handle.

== EDIT:RESOLVED ==

I should have used os.Std.Fd() instead of f.Fd(). My bad. I have it working in Windows now.

ghost commented 2 years ago

@jherman

Glad you have made it working, just comment for others may have the same issue:

term.MakeRaw

If you mean golang.org/x/sys/term.MakeRaw, that's meant for windows console, not conpty.

ref:

ghost commented 2 years ago

@creack any chance to test it again? I'm pretty confident it works now.

jherman commented 2 years ago

@jeffreystoke Thanks for the reply. I was able to make it work using the sample code in the readme, with only commenting out the section involving resize of the console. I still haven't found a good way to resize the console by listening for some event vs an inefficient polling for a size change.

I did find an issue with running interactive console UI's like FAR manager. You can't navigate or pretty much do anything with the function keys. This does work on the *nix bash sessions. Can you confirm if it's just me? If so, can you provide a working sample?

For those interested in the code I used:

package main

import (
    "io"
    "log"
    "os"
    "os/exec"

    "github.com/creack/pty"
    "golang.org/x/term"
)

func test() error {
    // Create arbitrary command.
    c := exec.Command("powershell")

    // Start the command with a pty.
    ptmx, err := pty.Start(c)
    if err != nil {
        return err
    }
    // Make sure to close the pty at the end.
    defer func() { _ = ptmx.Close() }() // Best effort.

    // Set stdin in raw mode.
    oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
    if err != nil {
        panic(err)
    }
    defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.

    // Copy stdin to the pty and the pty to stdout.
    // NOTE: The goroutine will keep reading until the next keystroke before returning.
    go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
    _, _ = io.Copy(os.Stdout, ptmx)

    return nil
}

func main() {
    if err := test(); err != nil {
        log.Fatal(err)
    }
}
ghost commented 2 years ago

@jherman

You can't navigate or pretty much do anything with the function keys.

Looks like a terminal escape sequence translation issue, result from my quick search suggests you should turn on or off the translation depending on your terminal emulator implementation. (windows.SetConsoleMode(handle, state | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING))

Ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

photostorm commented 2 years ago

@creack I know it been a couple months, but what are the tasks you would like done for windows support for it to be merge. I can continue PR.

geekros commented 1 year ago

Can I use it on Windows?

kcmvp commented 2 months ago

any update on this?