mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			92 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package gopass
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
)
 | 
						|
 | 
						|
var defaultGetCh = func() (byte, error) {
 | 
						|
	buf := make([]byte, 1)
 | 
						|
	if n, err := os.Stdin.Read(buf); n == 0 || err != nil {
 | 
						|
		if err != nil {
 | 
						|
			return 0, err
 | 
						|
		}
 | 
						|
		return 0, io.EOF
 | 
						|
	}
 | 
						|
	return buf[0], nil
 | 
						|
}
 | 
						|
 | 
						|
var (
 | 
						|
	maxLength            = 512
 | 
						|
	ErrInterrupted       = errors.New("interrupted")
 | 
						|
	ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength)
 | 
						|
 | 
						|
	// Provide variable so that tests can provide a mock implementation.
 | 
						|
	getch = defaultGetCh
 | 
						|
)
 | 
						|
 | 
						|
// getPasswd returns the input read from terminal.
 | 
						|
// If masked is true, typing will be matched by asterisks on the screen.
 | 
						|
// Otherwise, typing will echo nothing.
 | 
						|
func getPasswd(masked bool) ([]byte, error) {
 | 
						|
	var err error
 | 
						|
	var pass, bs, mask []byte
 | 
						|
	if masked {
 | 
						|
		bs = []byte("\b \b")
 | 
						|
		mask = []byte("*")
 | 
						|
	}
 | 
						|
 | 
						|
	if isTerminal(os.Stdin.Fd()) {
 | 
						|
		if oldState, err := makeRaw(os.Stdin.Fd()); err != nil {
 | 
						|
			return pass, err
 | 
						|
		} else {
 | 
						|
			defer restore(os.Stdin.Fd(), oldState)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Track total bytes read, not just bytes in the password.  This ensures any
 | 
						|
	// errors that might flood the console with nil or -1 bytes infinitely are
 | 
						|
	// capped.
 | 
						|
	var counter int
 | 
						|
	for counter = 0; counter <= maxLength; counter++ {
 | 
						|
		if v, e := getch(); e != nil {
 | 
						|
			err = e
 | 
						|
			break
 | 
						|
		} else if v == 127 || v == 8 {
 | 
						|
			if l := len(pass); l > 0 {
 | 
						|
				pass = pass[:l-1]
 | 
						|
				fmt.Print(string(bs))
 | 
						|
			}
 | 
						|
		} else if v == 13 || v == 10 {
 | 
						|
			break
 | 
						|
		} else if v == 3 {
 | 
						|
			err = ErrInterrupted
 | 
						|
			break
 | 
						|
		} else if v != 0 {
 | 
						|
			pass = append(pass, v)
 | 
						|
			fmt.Print(string(mask))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if counter > maxLength {
 | 
						|
		err = ErrMaxLengthExceeded
 | 
						|
	}
 | 
						|
 | 
						|
	fmt.Println()
 | 
						|
	return pass, err
 | 
						|
}
 | 
						|
 | 
						|
// GetPasswd returns the password read from the terminal without echoing input.
 | 
						|
// The returned byte array does not include end-of-line characters.
 | 
						|
func GetPasswd() ([]byte, error) {
 | 
						|
	return getPasswd(false)
 | 
						|
}
 | 
						|
 | 
						|
// GetPasswdMasked returns the password read from the terminal, echoing asterisks.
 | 
						|
// The returned byte array does not include end-of-line characters.
 | 
						|
func GetPasswdMasked() ([]byte, error) {
 | 
						|
	return getPasswd(true)
 | 
						|
}
 |