func (x *XCmd) StartPTY(stty []string) (xpty circuit.X, err error) { pty, tty, err := pty.Open() if err != nil { return nil, errors.Pack(err) } defer tty.Close() // Close our handle on the TTY after the child executes x.cmd.Stdout, x.cmd.Stdin, x.cmd.Stderr = tty, tty, tty x.cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} if err = x.cmd.Start(); err != nil { pty.Close() return nil, errors.Pack(err) } // sfs1/rex has comment that maybe tty flags cannot change until tty opened by child?? Not sure. if len(stty) > 0 { arg0 := []string{"-f", tty.Name()} if err = exec.Command("stty", append(arg0, "sane")...).Run(); err != nil { return nil, errors.Pack(err) } //log.Printf("PTY=%s, XX %#v", pty.Name(), append(arg0, stty...)) if err = exec.Command("stty", append(arg0, stty...)...).Run(); err != nil { return nil, errors.Pack(err) } } defer func() { go x.cmd.Wait() // Calling wait is necessary, otherwise child remains zombie }() return xyio.NewXReadWriteCloser(pty), nil }
func (x XServer) Profile(name string) (circuit.X, error) { r, err := x.server.Profile(name) if err != nil { return nil, errors.Pack(err) } return xio.NewXReadCloser(r), nil }
func (x XTerminal) Make(kind string, arg interface{}) (xelm circuit.X, err error) { elm, err := x.t.Make(kind, arg) if err != nil { return nil, xerrors.Pack(err) } return elm.X(), nil }
func (x XValve) Recv() (circuit.X, error) { r, err := x.Valve.Recv() if err != nil { return nil, errors.Pack(err) } return xio.NewXReadCloser(r), nil }
func (x XValve) Send() (circuit.X, error) { w, err := x.Valve.Send() if err != nil { return nil, errors.Pack(err) } return xio.NewXWriteCloser(w), nil }
func (x XContainer) Peek() (*ds.Stat, error) { stat, err := x.Container.Peek() return stat, errors.Pack(err) }
// Run executes the command and blocks until it completes, akin to os/exec.Cmd.Run func (x *XCmd) Run() error { return errors.Pack(x.cmd.Run()) }
func (x XValve) Close() error { return errors.Pack(x.Valve.Close()) }
func (x XCloser) Close() error { return errors.Pack(x.Closer.Close()) }
func (x XWriter) Write(p []byte) (int, error) { n, err := x.Writer.Write(p) return n, errors.Pack(err) }
func (x XServer) Rejoin(addr string) error { return errors.Pack(x.server.Rejoin(addr)) }
// Wait blocks until the process completes, akin to os/exec.Cmd.Wait func (x *XCmd) Wait() error { return errors.Pack(x.cmd.Wait()) }
func (x XContainer) Signal(sig string) error { return errors.Pack(x.Container.Signal(sig)) }
func (x XContainer) Wait() (*ds.Stat, error) { stat, err := x.Container.Wait() return stat, errors.Pack(err) }
func (x XProc) Signal(sig string) error { return errors.Pack(x.Proc.Signal(sig)) }
func (x XProc) Wait() (Stat, error) { stat, err := x.Proc.Wait() return pack(stat), errors.Pack(err) }
func pack(stat Stat) Stat { stat.Exit = errors.Pack(stat.Exit) return stat }
func (x XNameserver) Set(rr string) error { err := x.Nameserver.Set(rr) return errors.Pack(err) }
func (x XReader) Read(n int) ([]byte, error) { p := make([]byte, n) m, err := x.Reader.Read(p) return p[:m], errors.Pack(err) }