func (c *linuxConsole) dupStdio() error {
	slave, err := c.open(syscall.O_RDWR)
	if err != nil {
		return err
	}
	fd := int(slave.Fd())
	for _, i := range []int{0, 1, 2} {
		if err := syscall.Dup3(fd, i, 0); err != nil {
			return err
		}
	}
	return nil
}
dupStdio opens the slavePath for the console and dups the fds to the current
processes stdio, fd 0,1,2.
package libcontainer
import (
	"fmt"
	"os"
	"path/filepath"
	"syscall"
	"unsafe"
	"github.com/opencontainers/runc/libcontainer/label"
)
func NewConsole(uid, gid int) (Console, error) {
	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
	if err != nil {
		return nil, err
	}
	console, err := ptsname(master)
	if err != nil {
		return nil, err
	}
	if err := unlockpt(master); err != nil {
		return nil, err
	}
	if err := os.Chmod(console, 0600); err != nil {
		return nil, err
	}
	if err := os.Chown(console, uid, gid); err != nil {
		return nil, err
	}
	return &linuxConsole{
		slavePath: console,
		master:    master,
	}, nil
}
func newConsoleFromPath(slavePath string) *linuxConsole {
	return &linuxConsole{
		slavePath: slavePath,
	}
}
type linuxConsole struct {
	master    *os.File
	slavePath string
}
func (c *linuxConsole) Fd() uintptr {
	return c.master.Fd()
}
func (c *linuxConsole) Path() string {
	return c.slavePath
}
func (c *linuxConsole) Read(b []byte) (int, error) {
	return c.master.Read(b)
}
func (c *linuxConsole) Write(b []byte) (int, error) {
	return c.master.Write(b)
}
func (c *linuxConsole) Close() error {
	if m := c.master; m != nil {
		return m.Close()
	}
	return nil
}
func (c *linuxConsole) mount(rootfs, mountLabel string) error {
	oldMask := syscall.Umask(0000)
	defer syscall.Umask(oldMask)
	if err := label.SetFileLabel(c.slavePath, mountLabel); err != nil {
		return err
	}
	dest := filepath.Join(rootfs, "/dev/console")
	f, err := os.Create(dest)
	if err != nil && !os.IsExist(err) {
		return err
	}
	if f != nil {
		f.Close()
	}
	return syscall.Mount(c.slavePath, dest, "bind", syscall.MS_BIND, "")
}