Beispiel #1
0
// Run will launch the stage2 binary with the desired settings and execute the
// specified command. It will return once the stage2 has been started.
func (l *Launcher) Run(cmdargs ...string) (*os.Process, error) {
	args, extraFiles := l.generateArgs(cmdargs)

	// get the executable path to ourself
	self, err := os.Readlink("/proc/self/exe")
	if err != nil {
		return nil, err
	}

	// Create and initialize the spawnwer.
	cmd := exec.Command(self, args...)
	cmd.ExtraFiles = extraFiles
	if l.Stdin != nil {
		cmd.Stdin = l.Stdin
	}
	if l.Stdout != nil {
		cmd.Stdout = l.Stdout
	}
	if l.Stderr != nil {
		cmd.Stderr = l.Stderr
	}

	// The spawner keys off this environment variable to know when it is supposed
	// to run and take over execution.
	cmd.Env = []string{
		"SPAWNER_INTERCEPT=1",
	}

	// tty handling
	if str.IsTerminal(l.Stdin) {
		// Include setting the controlling tty, and close stdin (the slave pty)
		// after the command is started.
		cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
		l.postStart = append(l.postStart, func() { l.Stdin.Close() })
	} else {
		cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
	}

	// Start the container.
	if err := cmd.Start(); err != nil {
		return nil, err
	}

	// Run any postStart funcs, just to cleanup
	for _, f := range l.postStart {
		f()
	}

	// Wait for the command to ensure the process is reaped when its done.
	if l.Detach {
		go cmd.Wait()
	}

	return cmd.Process, nil
}
Beispiel #2
0
func main() {
	for _, label := range []string{
		"stdin", "stdout", "stderr",
	} {
		var fh *os.File

		switch label {
		case "stdin":
			fh = os.Stdin
		case "stdout":
			fh = os.Stdout
		case "stderr":
			fh = os.Stderr
		default:
			panic("unknown label")
		}

		if target.IsTerminal(fh) {
			fmt.Printf("%s is a terminal :)\n", label)
		} else {
			fmt.Printf("%s is not a terminal :(\n", label)
		}
	}
}