mirror of https://github.com/hashicorp/packer
pull/9037/head
parent
73c349d09c
commit
217dcbb97f
@ -0,0 +1,49 @@
|
||||
// STOLEN SHAMELESSLY FROM THE TERRAFORM REPO BECAUSE VENDORING OUT
|
||||
// WRAPPEDREADLINE AND WRAPPEDSTREAMS FELT LIKE TOO MUCH WORK.
|
||||
//
|
||||
// "a little copying is better than a lot of dependency"
|
||||
//
|
||||
// Package wrappedstreams provides access to the standard OS streams
|
||||
// (stdin, stdout, stderr) even if wrapped under panicwrap.
|
||||
package wrappedstreams
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/mitchellh/panicwrap"
|
||||
)
|
||||
|
||||
// Stdin returns the true stdin of the process.
|
||||
func Stdin() *os.File {
|
||||
stdin, _, _ := fds()
|
||||
return stdin
|
||||
}
|
||||
|
||||
// Stdout returns the true stdout of the process.
|
||||
func Stdout() *os.File {
|
||||
_, stdout, _ := fds()
|
||||
return stdout
|
||||
}
|
||||
|
||||
// Stderr returns the true stderr of the process.
|
||||
func Stderr() *os.File {
|
||||
_, _, stderr := fds()
|
||||
return stderr
|
||||
}
|
||||
|
||||
func fds() (stdin, stdout, stderr *os.File) {
|
||||
stdin, stdout, stderr = os.Stdin, os.Stdout, os.Stderr
|
||||
if panicwrap.Wrapped(nil) {
|
||||
initPlatform()
|
||||
stdin, stdout, stderr = wrappedStdin, wrappedStdout, wrappedStderr
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// These are the wrapped standard streams. These are setup by the
|
||||
// platform specific code in initPlatform.
|
||||
var (
|
||||
wrappedStdin *os.File
|
||||
wrappedStdout *os.File
|
||||
wrappedStderr *os.File
|
||||
)
|
||||
@ -0,0 +1,21 @@
|
||||
// +build !windows
|
||||
|
||||
package wrappedstreams
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var initOnce sync.Once
|
||||
|
||||
func initPlatform() {
|
||||
// These must be initialized lazily, once it's been determined that this is
|
||||
// a wrapped process.
|
||||
initOnce.Do(func() {
|
||||
// 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)
|
||||
}
|
||||
Loading…
Reference in new issue