github.com/victortrac/packer@v0.7.6-0.20160602180447-63c7fdb6e41f/stdin.go (about)

     1  package main
     2  
     3  import (
     4  	"io"
     5  	"log"
     6  	"os"
     7  	"os/signal"
     8  )
     9  
    10  // setupStdin switches out stdin for a pipe. We do this so that we can
    11  // close the writer end of the pipe when we receive an interrupt so plugins
    12  // blocked on reading from stdin are unblocked.
    13  func setupStdin() {
    14  	// Create the pipe and swap stdin for the reader end
    15  	r, w, _ := os.Pipe()
    16  	originalStdin := os.Stdin
    17  	os.Stdin = r
    18  
    19  	// Create a goroutine that copies data from the original stdin
    20  	// into the writer end of the pipe forever.
    21  	go func() {
    22  		defer w.Close()
    23  		io.Copy(w, originalStdin)
    24  	}()
    25  
    26  	// Register a signal handler for interrupt in order to close the
    27  	// writer end of our pipe so that readers get EOF downstream.
    28  	ch := make(chan os.Signal, 1)
    29  	signal.Notify(ch, os.Interrupt)
    30  
    31  	go func() {
    32  		defer signal.Stop(ch)
    33  		defer w.Close()
    34  		<-ch
    35  		log.Println("Closing stdin because interrupt received.")
    36  	}()
    37  }