<commit_before>package main

import (
	"bytes"
	"code.google.com/p/go.net/proxy"
	"flag"
	"fmt"
	"github.com/calmh/mole/ansi"
	"github.com/calmh/mole/conf"
	"io/ioutil"
	"os"
	"strings"
	"time"
)

func init() {
	commands["dig"] = command{commandDig, msgDigShort}
}

func commandDig(args []string) error {
	fs := flag.NewFlagSet("dig", flag.ExitOnError)
	local := fs.Bool("l", false, "Local file, not remote tunnel definition")
	qualify := fs.Bool("q", false, "Use <host>.<tunnel> for host aliases instead of just <host>")
	fs.Usage = usageFor(fs, msgDigUsage)
	fs.Parse(args)
	args = fs.Args()

	if len(args) != 1 {
		fs.Usage()
		os.Exit(3)
	}

	// Fail early in case we don't have root since it's always required on
	// platforms where it matters
	requireRoot("dig")

	var err error

	cl := NewClient(serverAddress(), moleIni.Get("server", "fingerprint"))
	_, err = authenticated(cl, func() (interface{}, error) { return cl.Ping() })
	fatalErr(err)

	var tun string
	if *local {
		fd, err := os.Open(args[0])
		fatalErr(err)
		bs, err := ioutil.ReadAll(fd)
		fatalErr(err)
		tun, err = cl.Deobfuscate(string(bs))
		fatalErr(err)
	} else {
		tun, err = cl.Get(args[0])
		fatalErr(err)
	}

	tun, err = cl.Deobfuscate(tun)
	fatalErr(err)
	cfg, err := conf.Load(bytes.NewBufferString(tun))
	fatalErr(err)

	if cfg == nil {
		return fmt.Errorf("no tunnel loaded")
	}

	var addrs []string
	if remapIntfs {
		cfg.Remap()
	} else {
		addrs = missingAddresses(cfg)
		if len(addrs) > 0 {
			addAddresses(addrs)
		}
	}

	infoln(sshPathStr(cfg.General.Main, cfg), "...")

	var vpn VPN
	if cfg.Vpnc != nil {
		vpn, err = startVpn("vpnc", cfg)
		fatalErr(err)
	} else if cfg.OpenConnect != nil {
		vpn, err = startVpn("openconnect", cfg)
		fatalErr(err)
	}

	var dialer Dialer = proxy.Direct
	if mh := cfg.General.Main; mh != "" {
		sshConn, err := sshHost(mh, cfg)
		fatalErr(err)
		dialer = sshConn

		// A REALY dirty keepalive mechanism.
		sess, err := sshConn.NewSession()
		fatalErr(err)
		stdout, err := sess.StdoutPipe()
		fatalErr(err)
		stderr, err := sess.StderrPipe()
		fatalErr(err)
		stdin, err := sess.StdinPipe()
		fatalErr(err)
		err = sess.Shell()
		fatalErr(err)

		go func() {
			bs := make([]byte, 1024)
			for {
				debugln("shell read stdout")
				_, err := stdout.Read(bs)
				fatalErr(err)
			}
		}()

		go func() {
			bs := make([]byte, 1024)
			for {
				debugln("shell read stderr")
				_, err := stderr.Read(bs)
				fatalErr(err)
			}
		}()

		go func() {
			for {
				time.Sleep(30 * time.Second)
				debugln("shell write")
				_, err := stdin.Write([]byte("\n"))
				fatalErr(err)
			}
		}()
	}

	fwdChan := startForwarder(dialer)
	sendForwards(fwdChan, cfg)

	setupHostsFile(args[0], cfg, *qualify)<commit_msg>Warn instead of exiting on keepalive errors<commit_after>package main

import (
	"bytes"
	"code.google.com/p/go.net/proxy"
	"flag"
	"fmt"
	"github.com/calmh/mole/ansi"
	"github.com/calmh/mole/conf"
	"io/ioutil"
	"os"
	"strings"
	"time"
)

func init() {
	commands["dig"] = command{commandDig, msgDigShort}
}

func commandDig(args []string) error {
	fs := flag.NewFlagSet("dig", flag.ExitOnError)
	local := fs.Bool("l", false, "Local file, not remote tunnel definition")
	qualify := fs.Bool("q", false, "Use <host>.<tunnel> for host aliases instead of just <host>")
	fs.Usage = usageFor(fs, msgDigUsage)
	fs.Parse(args)
	args = fs.Args()

	if len(args) != 1 {
		fs.Usage()
		os.Exit(3)
	}

	// Fail early in case we don't have root since it's always required on
	// platforms where it matters
	requireRoot("dig")

	var err error

	cl := NewClient(serverAddress(), moleIni.Get("server", "fingerprint"))
	_, err = authenticated(cl, func() (interface{}, error) { return cl.Ping() })
	fatalErr(err)

	var tun string
	if *local {
		fd, err := os.Open(args[0])
		fatalErr(err)
		bs, err := ioutil.ReadAll(fd)
		fatalErr(err)
		tun, err = cl.Deobfuscate(string(bs))
		fatalErr(err)
	} else {
		tun, err = cl.Get(args[0])
		fatalErr(err)
	}

	tun, err = cl.Deobfuscate(tun)
	fatalErr(err)
	cfg, err := conf.Load(bytes.NewBufferString(tun))
	fatalErr(err)

	if cfg == nil {
		return fmt.Errorf("no tunnel loaded")
	}

	var addrs []string
	if remapIntfs {
		cfg.Remap()
	} else {
		addrs = missingAddresses(cfg)
		if len(addrs) > 0 {
			addAddresses(addrs)
		}
	}

	infoln(sshPathStr(cfg.General.Main, cfg), "...")

	var vpn VPN
	if cfg.Vpnc != nil {
		vpn, err = startVpn("vpnc", cfg)
		fatalErr(err)
	} else if cfg.OpenConnect != nil {
		vpn, err = startVpn("openconnect", cfg)
		fatalErr(err)
	}

	var dialer Dialer = proxy.Direct
	if mh := cfg.General.Main; mh != "" {
		sshConn, err := sshHost(mh, cfg)
		fatalErr(err)
		dialer = sshConn

		// A REALY dirty keepalive mechanism.
		sess, err := sshConn.NewSession()
		fatalErr(err)
		stdout, err := sess.StdoutPipe()
		fatalErr(err)
		stderr, err := sess.StderrPipe()
		fatalErr(err)
		stdin, err := sess.StdinPipe()
		fatalErr(err)
		err = sess.Shell()
		fatalErr(err)

		go func() {
			bs := make([]byte, 1024)
			for {
				debugln("shell read stdout")
				_, err := stdout.Read(bs)
				if err != nil {
					warnln("keepalive stdout", err)
					return
				}
			}
		}()

		go func() {
			bs := make([]byte, 1024)
			for {
				debugln("shell read stderr")
				_, err := stderr.Read(bs)
				if err != nil {
					warnln("keepalive stderr", err)
					return
				}
			}
		}()

		go func() {
			for {
				time.Sleep(30 * time.Second)
				debugln("shell write")
				_, err := stdin.Write([]byte("\n"))
				if err != nil {
					warnln("keepalive stdin", err)
					return
				}
			}
		}()
	}

	fwdChan := startForwarder(dialer)
	sendForwards(fwdChan, cfg)

	setupHostsFile(args[0], cfg, *qualify)
{'fraction_non_alphanumeric': 0.16448763250883391, 'fraction_numerical': 0.005653710247349823, 'mean_word_length': 3.3815789473684212, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, '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': '189999', 'n_tokens_mistral': 2579, 'n_tokens_neox': 2235, 'n_words': 507}