func (ui *UI) monitorSys(ctx context.Context, cancel context.CancelFunc, sigCh chan os.Signal) {
	signal.Notify(sigCh)
	defer close(sigCh)
	defer signal.Stop(sigCh)
	for {
		select {
		case <-ctx.Done():
		case sig := <-sigCh:
			handler, exists := ui.sigHandlers[sig]
			if exists {
				sig = handler(sig)
			}
			if sig == os.Kill || sig == os.Interrupt {
				cancel()
			}
		}
	}
}
monitorSys monitors syscalls from the OS
package sand
import (
	"bytes"
	"context"
	"fmt"
	"github.com/pkg/errors"
	"io"
	"net"
	"os"
	"os/signal"
	"runtime"
	"sync"
)
var errNoEngine = errors.New("sand: engine must be non-null")
func IsRecoverable(err error) (root error, ok bool) {
	if err == nil {
		return nil, true
	}
	root = errors.Cause(err)
	if root == context.DeadlineExceeded || root == context.Canceled {
		return root, true
	}
errTypes:
	switch v := root.(type) {
	case net.Error:
	case runtime.Error:
	case newLineErr:
		root = v.werr
		goto errTypes
	default:
		return root, true
	}
	return
}
type SignalHandler func(os.Signal) os.Signal
type Option func(*UI)
func WithPrefix(prefix string) Option {
	return func(ui *UI) {
		ui.prefix = []byte(prefix)
	}
}
func WithIO(in io.Reader, out io.Writer) Option {
	return func(ui *UI) {
		ui.i = in
		ui.o = out
	}
}
func WithSignalHandlers(handlers map[os.Signal]SignalHandler) Option {
	return func(ui *UI) {
		ui.sigHandlers = handlers
	}
}
type UI struct {
	i           io.Reader
	o           io.Writer
	prefix      []byte
	sigHandlers map[os.Signal]SignalHandler
	ctx context.Context  
}
func (ui *UI) SetPrefix(prefix string) {
	ui.prefix = []byte(prefix)
}
func (ui *UI) SetIO(in io.Reader, out io.Writer) {
	ui.i = in
	ui.o = out
}
func Run(ctx context.Context, eng Engine, opts ...Option) error {
	ui := new(UI)
	return ui.Run(ctx, eng, opts...)
}
const minRead = 512
type newLineErr struct {
	werr error
}
func (e newLineErr) Error() string {
	return fmt.Sprintf("sand: encountered error when writing newline, %s", e.werr)
}
func (ui *UI) Run(ctx context.Context, eng Engine, opts ...Option) (err error) {
	if eng == nil {
		panic(errNoEngine)
	}
	defer func() {
		if r := recover(); r != nil {
			rerr, ok := r.(error)
			if !ok {
				return
			}
			err = errors.Wrap(rerr, "sand: recovered from panic")
		}
	}()
	for _, opt := range opts {
		opt(ui)
	}
	var cancel context.CancelFunc
	if ctx == nil {
		ctx, cancel = context.WithCancel(context.Background())
	}
	ui.ctx = ctx
	if cancel == nil {
		ui.ctx, cancel = context.WithCancel(ctx)
	}
	defer cancel()
	reqCh := make(chan execReq)
	sigs := make(chan os.Signal, 1)
	defer close(reqCh)
	go ui.monitorSys(ui.ctx, cancel, sigs)
	ui.startEngine(ctx, eng, reqCh)
	defer func() {
		if err == nil || err == io.EOF {
			_, err = ui.o.Write([]byte("\n"))
			if err != nil {
				err = newLineErr{werr: err}
			}
			return
		}
	}()
	var n int
	for {
		_, err = ui.Write(nil)
		if err != nil {
			err = errors.Wrap(err, "sand: encountered error while writing prefix")
			return
		}
		b := make([]byte, minRead)
		n, err = ui.Read(b)
		if err != nil && err != io.EOF || n == 0 {
			return
		}
		idx := bytes.IndexByte(b, 0)
		if idx != -1 {
			b = b[:idx]
		}
		status := ui.exec(ui.ctx, string(b), reqCh)
		if status != 0 {
			return
		}
		if err == io.EOF {
			return
		}
	}
}
var engines = struct {
	sync.Mutex
	engs map[Engine]chan chan execReq
}{
	engs: make(map[Engine]chan chan execReq),
}
func (ui *UI) startEngine(ctx context.Context, eng Engine, uiReqCh chan execReq) {
	engines.Lock()
	reqCh, exists := engines.engs[eng]
	if !exists {
		reqCh = make(chan chan execReq)
		engines.engs[eng] = reqCh
		go runEngine(ctx, eng, reqCh)
	}
	engines.Unlock()
	reqCh <- uiReqCh
}