// Start implementation of communicator.Communicator interface
func (c *MockCommunicator) Start(r *remote.Cmd) error {
	if !c.Commands[r.Command] {
		return fmt.Errorf("Command not found!")
	}

	r.SetExited(0)

	return nil
}
// Start implementation of communicator.Communicator interface
func (c *Communicator) Start(cmd *remote.Cmd) error {
	session, err := c.newSession()
	if err != nil {
		return err
	}

	// Setup our session
	session.Stdin = cmd.Stdin
	session.Stdout = cmd.Stdout
	session.Stderr = cmd.Stderr

	if !c.config.noPty {
		// Request a PTY
		termModes := ssh.TerminalModes{
			ssh.ECHO:          0,     // do not echo
			ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
			ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
		}

		if err := session.RequestPty("xterm", 80, 40, termModes); err != nil {
			return err
		}
	}

	log.Printf("starting remote command: %s", cmd.Command)
	err = session.Start(cmd.Command + "\n")
	if err != nil {
		return err
	}

	// Start a goroutine to wait for the session to end and set the
	// exit boolean and status.
	go func() {
		defer session.Close()

		err := session.Wait()
		exitStatus := 0
		if err != nil {
			exitErr, ok := err.(*ssh.ExitError)
			if ok {
				exitStatus = exitErr.ExitStatus()
			}
		}

		log.Printf("remote command exited with '%d': %s", exitStatus, cmd.Command)
		cmd.SetExited(exitStatus)
	}()

	return nil
}
func runCommand(shell *winrm.Shell, cmd *winrm.Command, rc *remote.Cmd) {
	defer shell.Close()

	var wg sync.WaitGroup
	go func() {
		wg.Add(1)
		io.Copy(rc.Stdout, cmd.Stdout)
		wg.Done()
	}()
	go func() {
		wg.Add(1)
		io.Copy(rc.Stderr, cmd.Stderr)
		wg.Done()
	}()

	cmd.Wait()
	wg.Wait()
	rc.SetExited(cmd.ExitCode())
}