Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5f21a14

Browse files
authored
bug: Don't try to handle SIGINT when prompting for passwords (#1498)
1 parenta3556b1 commit5f21a14

File tree

6 files changed

+108
-17
lines changed

6 files changed

+108
-17
lines changed

‎cli/cliui/prompt.go‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ func Prompt(cmd *cobra.Command, opts PromptOptions) (string, error) {
3434
_,_=fmt.Fprint(cmd.OutOrStdout(),Styles.Placeholder.Render("("+opts.Default+") "))
3535
}
3636
interrupt:=make(chan os.Signal,1)
37-
signal.Notify(interrupt,os.Interrupt)
38-
defersignal.Stop(interrupt)
3937

4038
errCh:=make(chanerror,1)
4139
lineCh:=make(chanstring)
@@ -45,8 +43,12 @@ func Prompt(cmd *cobra.Command, opts PromptOptions) (string, error) {
4543

4644
inFile,isInputFile:=cmd.InOrStdin().(*os.File)
4745
ifopts.Secret&&isInputFile&&isatty.IsTerminal(inFile.Fd()) {
46+
// we don't install a signal handler here because speakeasy has its own
4847
line,err=speakeasy.Ask("")
4948
}else {
49+
signal.Notify(interrupt,os.Interrupt)
50+
defersignal.Stop(interrupt)
51+
5052
reader:=bufio.NewReader(cmd.InOrStdin())
5153
line,err=reader.ReadString('\n')
5254

‎cli/cliui/prompt_test.go‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ package cliui_test
22

33
import (
44
"context"
5+
"os"
6+
"os/exec"
57
"testing"
8+
"time"
69

710
"github.com/spf13/cobra"
811
"github.com/stretchr/testify/require"
912

1013
"github.com/coder/coder/cli/cliui"
14+
"github.com/coder/coder/pty"
1115
"github.com/coder/coder/pty/ptytest"
1216
)
1317

@@ -110,3 +114,56 @@ func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions) (string, error) {
110114
cmd.SetIn(ptty.Input())
111115
returnvalue,cmd.ExecuteContext(context.Background())
112116
}
117+
118+
funcTestPasswordTerminalState(t*testing.T) {
119+
ifos.Getenv("TEST_SUBPROCESS")=="1" {
120+
passwordHelper()
121+
return
122+
}
123+
t.Parallel()
124+
125+
ptty:=ptytest.New(t)
126+
ptyWithFlags,ok:=ptty.PTY.(pty.WithFlags)
127+
if!ok {
128+
t.Skip("unable to check PTY local echo on this platform")
129+
}
130+
131+
cmd:=exec.Command(os.Args[0],"-test.run=TestPasswordTerminalState")//nolint:gosec
132+
cmd.Env=append(os.Environ(),"TEST_SUBPROCESS=1")
133+
// connect the child process's stdio to the PTY directly, not via a pipe
134+
cmd.Stdin=ptty.Input().Reader
135+
cmd.Stdout=ptty.Output().Writer
136+
cmd.Stderr=os.Stderr
137+
err:=cmd.Start()
138+
require.NoError(t,err)
139+
process:=cmd.Process
140+
deferprocess.Kill()
141+
142+
ptty.ExpectMatch("Password: ")
143+
time.Sleep(100*time.Millisecond)// wait for child process to turn off echo and start reading input
144+
145+
echo,err:=ptyWithFlags.EchoEnabled()
146+
require.NoError(t,err)
147+
require.False(t,echo,"echo is on while reading password")
148+
149+
err=process.Signal(os.Interrupt)
150+
require.NoError(t,err)
151+
_,err=process.Wait()
152+
require.NoError(t,err)
153+
154+
echo,err=ptyWithFlags.EchoEnabled()
155+
require.NoError(t,err)
156+
require.True(t,echo,"echo is off after reading password")
157+
}
158+
159+
funcpasswordHelper() {
160+
cmd:=&cobra.Command{
161+
Run:func(cmd*cobra.Command,args []string) {
162+
cliui.Prompt(cmd, cliui.PromptOptions{
163+
Text:"Password:",
164+
Secret:true,
165+
})
166+
},
167+
}
168+
cmd.ExecuteContext(context.Background())
169+
}

‎pty/pty.go‎

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package pty
22

33
import (
44
"io"
5+
"os"
56
)
67

78
// PTY is a minimal interface for interacting with a TTY.
@@ -14,26 +15,46 @@ type PTY interface {
1415
// uses the output stream for writing.
1516
//
1617
// The same stream could be read to validate output.
17-
Output()io.ReadWriter
18+
Output()ReadWriter
1819

1920
// Input handles TTY input.
2021
//
2122
// cmd.SetInput(pty.Input()) would be used to specify a command
2223
// uses the PTY input for reading.
2324
//
2425
// The same stream would be used to provide user input: pty.Input().Write(...)
25-
Input()io.ReadWriter
26+
Input()ReadWriter
2627

2728
// Resize sets the size of the PTY.
2829
Resize(heightuint16,widthuint16)error
2930
}
3031

32+
// WithFlags represents a PTY whose flags can be inspected, in particular
33+
// to determine whether local echo is enabled.
34+
typeWithFlagsinterface {
35+
PTY
36+
37+
// EchoEnabled determines whether local echo is currently enabled for this terminal.
38+
EchoEnabled() (bool,error)
39+
}
40+
3141
// New constructs a new Pty.
3242
funcNew() (PTY,error) {
3343
returnnewPty()
3444
}
3545

36-
typereadWriterstruct {
37-
io.Reader
38-
io.Writer
46+
// ReadWriter is an implementation of io.ReadWriter that wraps two separate
47+
// underlying file descriptors, one for reading and one for writing, and allows
48+
// them to be accessed separately.
49+
typeReadWriterstruct {
50+
Reader*os.File
51+
Writer*os.File
52+
}
53+
54+
func (rwReadWriter)Read(p []byte) (int,error) {
55+
returnrw.Reader.Read(p)
56+
}
57+
58+
func (rwReadWriter)Write(p []byte) (int,error) {
59+
returnrw.Writer.Write(p)
3960
}

‎pty/pty_linux.go‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// go:build linux
2+
3+
package pty
4+
5+
import"golang.org/x/sys/unix"
6+
7+
func (p*otherPty)EchoEnabled() (bool,error) {
8+
termios,err:=unix.IoctlGetTermios(int(p.pty.Fd()),unix.TCGETS)
9+
iferr!=nil {
10+
returnfalse,err
11+
}
12+
return (termios.Lflag&unix.ECHO)!=0,nil
13+
}

‎pty/pty_other.go‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package pty
55

66
import (
7-
"io"
87
"os"
98
"sync"
109

@@ -28,15 +27,15 @@ type otherPty struct {
2827
pty,tty*os.File
2928
}
3029

31-
func (p*otherPty)Input()io.ReadWriter {
32-
returnreadWriter{
30+
func (p*otherPty)Input()ReadWriter {
31+
returnReadWriter{
3332
Reader:p.tty,
3433
Writer:p.pty,
3534
}
3635
}
3736

38-
func (p*otherPty)Output()io.ReadWriter {
39-
returnreadWriter{
37+
func (p*otherPty)Output()ReadWriter {
38+
returnReadWriter{
4039
Reader:p.pty,
4140
Writer:p.tty,
4241
}

‎pty/pty_windows.go‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package pty
55

66
import (
7-
"io"
87
"os"
98
"sync"
109
"unsafe"
@@ -67,15 +66,15 @@ type ptyWindows struct {
6766
closedbool
6867
}
6968

70-
func (p*ptyWindows)Output()io.ReadWriter {
71-
returnreadWriter{
69+
func (p*ptyWindows)Output()ReadWriter {
70+
returnReadWriter{
7271
Reader:p.outputRead,
7372
Writer:p.outputWrite,
7473
}
7574
}
7675

77-
func (p*ptyWindows)Input()io.ReadWriter {
78-
returnreadWriter{
76+
func (p*ptyWindows)Input()ReadWriter {
77+
returnReadWriter{
7978
Reader:p.inputRead,
8079
Writer:p.inputWrite,
8180
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp