forked from TrueCloudLab/rclone
Compare commits
12 commits
tcl/master
...
pr-6474-pr
Author | SHA1 | Date | |
---|---|---|---|
|
3450d049b5 | ||
|
16b383e18f | ||
|
d59909fb8c | ||
|
cec47699d3 | ||
|
0687a263f8 | ||
|
3192e00f4f | ||
|
14534c573a | ||
|
408d0c729b | ||
|
a716dc2533 | ||
|
28f0c08a98 | ||
|
458c477ad8 | ||
|
7130a6d2e4 |
7 changed files with 45 additions and 28 deletions
|
@ -62,7 +62,7 @@ func startProgress() func() {
|
|||
printProgress("")
|
||||
fs.LogPrint = oldLogPrint
|
||||
operations.SyncPrintf = oldSyncPrint
|
||||
fmt.Println("")
|
||||
fmt.Fprintln(terminal.Out, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,6 @@ var (
|
|||
// When nil, no encryption will be used for saving.
|
||||
configKey []byte
|
||||
|
||||
// PasswordPromptOutput is output of prompt for password
|
||||
PasswordPromptOutput = os.Stderr
|
||||
|
||||
// PassConfigKeyForDaemonization if set to true, the configKey
|
||||
// is obscured with obscure.Obscure and saved to a temp file
|
||||
// when it is calculated from the password. The path of that
|
||||
|
|
|
@ -716,9 +716,9 @@ func checkPassword(password string) (string, error) {
|
|||
|
||||
// GetPassword asks the user for a password with the prompt given.
|
||||
func GetPassword(prompt string) string {
|
||||
_, _ = fmt.Fprintln(PasswordPromptOutput, prompt)
|
||||
_, _ = fmt.Fprintln(terminal.Out, prompt)
|
||||
for {
|
||||
_, _ = fmt.Fprint(PasswordPromptOutput, "password:")
|
||||
_, _ = fmt.Fprint(terminal.Out, "password:")
|
||||
password := ReadPassword()
|
||||
password, err := checkPassword(password)
|
||||
if err == nil {
|
||||
|
|
|
@ -9,17 +9,17 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/rclone/rclone/fs/config"
|
||||
"github.com/rclone/rclone/lib/terminal"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// redirectStderr to the file passed in
|
||||
func redirectStderr(f *os.File) {
|
||||
passPromptFd, err := unix.Dup(int(os.Stderr.Fd()))
|
||||
termFd, err := unix.Dup(int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to duplicate stderr: %v", err)
|
||||
}
|
||||
config.PasswordPromptOutput = os.NewFile(uintptr(passPromptFd), "passPrompt")
|
||||
terminal.RawOut = os.NewFile(uintptr(termFd), "termOut")
|
||||
err = unix.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to redirect stderr to file: %v", err)
|
||||
|
|
|
@ -12,29 +12,43 @@ package log
|
|||
import (
|
||||
"log"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/rclone/rclone/lib/terminal"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.MustLoadDLL("kernel32.dll")
|
||||
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
|
||||
)
|
||||
|
||||
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
|
||||
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
|
||||
if r0 == 0 {
|
||||
if e1 != 0 {
|
||||
return error(e1)
|
||||
}
|
||||
return syscall.EINVAL
|
||||
// dup oldfd creating a functional copy as newfd
|
||||
// conceptually the same as the unix `dup()` function
|
||||
func dup(oldfd uintptr) (newfd uintptr, err error) {
|
||||
var (
|
||||
newfdHandle windows.Handle
|
||||
processHandle = windows.CurrentProcess()
|
||||
)
|
||||
err = windows.DuplicateHandle(
|
||||
processHandle, // hSourceProcessHandle
|
||||
windows.Handle(oldfd), // hSourceHandle
|
||||
processHandle, // hTargetProcessHandle
|
||||
&newfdHandle, // lpTargetHandle
|
||||
0, // dwDesiredAccess
|
||||
true, // bInheritHandle
|
||||
windows.DUPLICATE_SAME_ACCESS, // dwOptions
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return nil
|
||||
return uintptr(newfdHandle), nil
|
||||
}
|
||||
|
||||
// redirectStderr to the file passed in
|
||||
func redirectStderr(f *os.File) {
|
||||
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
|
||||
termFd, err := dup(os.Stderr.Fd())
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to duplicate stderr: %v", err)
|
||||
}
|
||||
terminal.RawOut = os.NewFile(termFd, "termOut")
|
||||
err = windows.SetStdHandle(windows.STD_ERROR_HANDLE, windows.Handle(f.Fd()))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to redirect stderr to file: %v", err)
|
||||
}
|
||||
os.Stderr = f
|
||||
}
|
||||
|
|
|
@ -68,17 +68,23 @@ const (
|
|||
var (
|
||||
// make sure that start is only called once
|
||||
once sync.Once
|
||||
|
||||
// RawOut is the underlying *os.File intended for terminal output
|
||||
RawOut = os.Stderr
|
||||
)
|
||||
|
||||
// Start the terminal - must be called before use
|
||||
func Start() {
|
||||
once.Do(func() {
|
||||
f := os.Stdout
|
||||
f := RawOut
|
||||
if !IsTerminal(int(f.Fd())) {
|
||||
// If stdout not a tty then remove escape codes
|
||||
// If output is not a tty then remove escape codes
|
||||
Out = colorable.NewNonColorable(f)
|
||||
} else if runtime.GOOS == "windows" && os.Getenv("TERM") != "" {
|
||||
// If TERM is set just use stdout
|
||||
// If TERM is set on Windows then we should just send output
|
||||
// straight to the terminal for cygwin/git bash environments.
|
||||
// We don't want to use NewColorable here because it will
|
||||
// use Windows console calls which cygwin/git bash don't support.
|
||||
Out = f
|
||||
} else {
|
||||
Out = colorable.NewColorable(f)
|
||||
|
|
|
@ -34,5 +34,5 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||
|
||||
// WriteTerminalTitle writes a string to the terminal title
|
||||
func WriteTerminalTitle(title string) {
|
||||
fmt.Printf(ChangeTitle + title + BEL)
|
||||
fmt.Fprintf(Out, ChangeTitle+title+BEL)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue