helper/wrappedstreams: get original console input/output on Windows
Fixes #10266 panicwrap was using Extrafiles to get the original standard streams for `terraform console`. This doesn't work on Windows. Instead, we must use the Win32 APIs to get the exact handles.
This commit is contained in:
parent
50c1e875d0
commit
fd36b548c5
|
@ -38,10 +38,15 @@ func Stderr() *os.File {
|
||||||
return stderr
|
return stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are the wrapped streams. There doesn't appear to be a negative
|
// These are the wrapped standard streams. These are setup by the
|
||||||
// impact of opening these files even if the file descriptor doesn't exist.
|
// platform specific code in initPlatform.
|
||||||
var (
|
var (
|
||||||
wrappedStdin = os.NewFile(uintptr(3), "stdin")
|
wrappedStdin *os.File
|
||||||
wrappedStdout = os.NewFile(uintptr(4), "stdout")
|
wrappedStdout *os.File
|
||||||
wrappedStderr = os.NewFile(uintptr(5), "stderr")
|
wrappedStderr *os.File
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Initialize the platform-specific code
|
||||||
|
initPlatform()
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package wrappedstreams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initPlatform() {
|
||||||
|
// The standard streams are passed in via extra file descriptors.
|
||||||
|
wrappedStdin = os.NewFile(uintptr(3), "stdin")
|
||||||
|
wrappedStdout = os.NewFile(uintptr(4), "stdout")
|
||||||
|
wrappedStderr = os.NewFile(uintptr(5), "stderr")
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package wrappedstreams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initPlatform() {
|
||||||
|
wrappedStdin = openConsole("CONIN$", os.Stdin)
|
||||||
|
wrappedStdout = openConsole("CONOUT$", os.Stdout)
|
||||||
|
wrappedStderr = wrappedStdout
|
||||||
|
}
|
||||||
|
|
||||||
|
// openConsole opens a console handle, using a backup if it fails.
|
||||||
|
// This is used to get the exact console handle instead of the redirected
|
||||||
|
// handles from panicwrap.
|
||||||
|
func openConsole(name string, backup *os.File) *os.File {
|
||||||
|
// Convert to UTF16
|
||||||
|
path, err := syscall.UTF16PtrFromString(name)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] wrappedstreams: %s", err)
|
||||||
|
return backup
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the share mode
|
||||||
|
var shareMode uint32
|
||||||
|
switch name {
|
||||||
|
case "CONIN$":
|
||||||
|
shareMode = syscall.FILE_SHARE_READ
|
||||||
|
case "CONOUT$":
|
||||||
|
shareMode = syscall.FILE_SHARE_WRITE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the file
|
||||||
|
h, err := syscall.CreateFile(
|
||||||
|
path,
|
||||||
|
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
|
||||||
|
shareMode,
|
||||||
|
nil,
|
||||||
|
syscall.OPEN_EXISTING,
|
||||||
|
0, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] wrappedstreams: %s", err)
|
||||||
|
return backup
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the Go file
|
||||||
|
return os.NewFile(uintptr(h), name)
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -151,7 +152,13 @@ func Wrap(c *WrapConfig) (int, error) {
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = stdout_w
|
cmd.Stdout = stdout_w
|
||||||
cmd.Stderr = stderr_w
|
cmd.Stderr = stderr_w
|
||||||
|
|
||||||
|
// Windows doesn't support this, but on other platforms pass in
|
||||||
|
// the original file descriptors so they can be used.
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
cmd.ExtraFiles = []*os.File{os.Stdin, os.Stdout, os.Stderr}
|
cmd.ExtraFiles = []*os.File{os.Stdin, os.Stdout, os.Stderr}
|
||||||
|
}
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return 1, err
|
return 1, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1915,10 +1915,10 @@
|
||||||
"revision": "314aad379a39f6ad5bcca278e6757d9abbb3a52e"
|
"revision": "314aad379a39f6ad5bcca278e6757d9abbb3a52e"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "wqU8bs9c+xm0f07t6ajQFWYS+rE=",
|
"checksumSHA1": "kTntIB9SdU1NsCqKwDkUr99qaj0=",
|
||||||
"path": "github.com/mitchellh/panicwrap",
|
"path": "github.com/mitchellh/panicwrap",
|
||||||
"revision": "168f3680ad986108df63bae07da2978f51c4ac8e",
|
"revision": "fde185d0dfb5ecac6e6b201e8855da798ebcd76f",
|
||||||
"revisionTime": "2016-11-14T06:37:33Z"
|
"revisionTime": "2016-11-21T18:34:54Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "github.com/mitchellh/prefixedio",
|
"path": "github.com/mitchellh/prefixedio",
|
||||||
|
|
Loading…
Reference in New Issue