<commit_before>package batch

import (
	"bufio"
	"fmt"
	"github.com/qjpcpu/sesh/golang.org/x/crypto/ssh"
	"github.com/qjpcpu/sesh/golang.org/x/crypto/ssh/agent"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"sync"
)

type Task struct {
	User     string
	Password string
	Keyfile  string
	Output   io.Writer
	Errout   io.Writer
	Cmd      string
	Host     string
	Timeout  int
	*sync.WaitGroup
}

func NewTask(host, user, password, keyfile, cmd string, output, err_out io.Writer, wg *sync.WaitGroup) (task *Task) {
	wg.Add(1)
	task = &Task{
		User:     user,
		Password: password,
		Keyfile:  keyfile,
		Output:   output,
		Errout:   err_out,
		Cmd:      cmd,
		Host:     host,
		Timeout:  5,
	}
	task.WaitGroup = wg
	return
}

func getkey(file string) (key ssh.Signer, err error) {
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	key, err = ssh.ParsePrivateKey(buf)
	if err != nil {
		return
	}
	return

}
func (task *Task) Work() {
	if task.WaitGroup != nil {
		defer task.Done()
	}
	ssh_agent := func() ssh.AuthMethod {
		if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
			return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
		}
		return nil
	}
	auths := []ssh.AuthMethod{
		ssh.Password(task.Password),
	}
	if os.Getenv("SSH_AUTH_SOCK") != "" {
		auths = append(auths, ssh_agent())
	}
	if task.Keyfile != "" {
		if key, err := getkey(task.Keyfile); err == nil {
			auths = append(auths, ssh.PublicKeys(key))
		}
	}
	config := &ssh.ClientConfig{
		User: task.User,
		Auth: auths,
	}
	conn, err := ssh.Dial("tcp", task.Host+":22", config)
	if err != nil {
		if task.Password != "" && strings.Contains(err.Error(), "unable to authenticate, attempted methods [none publickey]") {
			config = &ssh.ClientConfig{
				User: task.User,
				Auth: []ssh.AuthMethod{ssh.Password(task.Password)},
			}
			conn, err = ssh.Dial("tcp", task.Host+":22", config)
			if err != nil {
				fmt.Fprintln(task.Errout, "unable to connect: ", err.Error())
				return
			}
		} else {
			fmt.Fprintln(task.Errout, "unable to connect: ", err.Error())
			return
		}
	}
	defer conn.Close()
	session, err := conn.NewSession()
	if err != nil {
		fmt.Fprintln(task.Errout, "Failed to create session: "+err.Error())
		return
	}
	defer session.Close()

	session.Stdout = task.Output
	session.Stderr = task.Output
	session.Run(task.Cmd)
}

func (task *Task) Login() {
	ssh_agent := func() ssh.AuthMethod {
		if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
			return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
		}
		return nil
	}
	auths := []ssh.AuthMethod{
		ssh.Password(task.Password),
	}
	if os.Getenv("SSH_AUTH_SOCK") != "" {
		auths = append(auths, ssh_agent())
	}
	if task.Keyfile != "" {
		if key, err := getkey(task.Keyfile); err == nil {
			auths = append(auths, ssh.PublicKeys(key))
		}
	}
	config := &ssh.ClientConfig{
		User: task.User,
		Auth: auths,
	}
	conn, err := ssh.Dial("tcp", task.Host+":22", config)
	if err != nil {
		fmt.Fprintln(task.Errout, "unable to connect: ", err.Error())
		return
	}
	defer conn.Close()
	session, err := conn.NewSession()
	if err != nil {
		fmt.Fprintln(task.Errout, "Failed to create session: "+err.Error())
		return
	}
	defer session.Close()
	// Set IO
	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	in, _ := session.StdinPipe()
<commit_msg>fix osx ssh agent bug<commit_after>package batch

import (
	"bufio"
	"fmt"
	"github.com/qjpcpu/sesh/golang.org/x/crypto/ssh"
	"github.com/qjpcpu/sesh/golang.org/x/crypto/ssh/agent"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"sync"
)

type Task struct {
	User     string
	Password string
	Keyfile  string
	Output   io.Writer
	Errout   io.Writer
	Cmd      string
	Host     string
	Timeout  int
	*sync.WaitGroup
}

func NewTask(host, user, password, keyfile, cmd string, output, err_out io.Writer, wg *sync.WaitGroup) (task *Task) {
	wg.Add(1)
	task = &Task{
		User:     user,
		Password: password,
		Keyfile:  keyfile,
		Output:   output,
		Errout:   err_out,
		Cmd:      cmd,
		Host:     host,
		Timeout:  5,
	}
	task.WaitGroup = wg
	return
}

func getkey(file string) (key ssh.Signer, err error) {
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	key, err = ssh.ParsePrivateKey(buf)
	if err != nil {
		return
	}
	return

}
func (task *Task) Work() {
	if task.WaitGroup != nil {
		defer task.Done()
	}
	ssh_agent := func() ssh.AuthMethod {
		if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
			return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
		}
		return nil
	}
	auths := []ssh.AuthMethod{
		ssh.Password(task.Password),
	}
	if os.Getenv("SSH_AUTH_SOCK") != "" {
		if sagt := ssh_agent(); sagt != nil {
			auths = append(auths, ssh_agent())
		}
	}
	if task.Keyfile != "" {
		if key, err := getkey(task.Keyfile); err == nil {
			auths = append(auths, ssh.PublicKeys(key))
		}
	}
	config := &ssh.ClientConfig{
		User: task.User,
		Auth: auths,
	}
	conn, err := ssh.Dial("tcp", task.Host+":22", config)
	if err != nil {
		if task.Password != "" && strings.Contains(err.Error(), "unable to authenticate, attempted methods [none publickey]") {
			config = &ssh.ClientConfig{
				User: task.User,
				Auth: []ssh.AuthMethod{ssh.Password(task.Password)},
			}
			conn, err = ssh.Dial("tcp", task.Host+":22", config)
			if err != nil {
				fmt.Fprintln(task.Errout, "unable to connect: ", err.Error())
				return
			}
		} else {
			fmt.Fprintln(task.Errout, "unable to connect: ", err.Error())
			return
		}
	}
	defer conn.Close()
	session, err := conn.NewSession()
	if err != nil {
		fmt.Fprintln(task.Errout, "Failed to create session: "+err.Error())
		return
	}
	defer session.Close()

	session.Stdout = task.Output
	session.Stderr = task.Output
	session.Run(task.Cmd)
}

func (task *Task) Login() {
	ssh_agent := func() ssh.AuthMethod {
		if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
			return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
		}
		return nil
	}
	auths := []ssh.AuthMethod{
		ssh.Password(task.Password),
	}
	if os.Getenv("SSH_AUTH_SOCK") != "" {
		if sagt := ssh_agent(); sagt != nil {
			auths = append(auths, ssh_agent())
		}
	}
	if task.Keyfile != "" {
		if key, err := getkey(task.Keyfile); err == nil {
			auths = append(auths, ssh.PublicKeys(key))
		}
	}
	config := &ssh.ClientConfig{
		User: task.User,
		Auth: auths,
	}
	conn, err := ssh.Dial("tcp", task.Host+":22", config)
	if err != nil {
		fmt.Fprintln(task.Errout, "unable to connect: ", err.Error())
		return
	}
	defer conn.Close()
	session, err := conn.NewSession()
	if err != nil {
		fmt.Fprintln(task.Errout, "Failed to create session: "+err.Error())
		return
	}
	defer session.Close()
	// Set IO
	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	in, _ := session.StdinPipe()

{'fraction_non_alphanumeric': 0.16371552975326562, 'fraction_numerical': 0.0023222060957910013, 'mean_word_length': 3.4258188824662814, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2674500', 'n_tokens_mistral': 2921, 'n_tokens_neox': 2679, 'n_words': 594}