func lazySetupPrefixes() { if prefix == nil { if !loggingEnabled { panic("attempting setup before logging enabled") } prefix = map[string]string{ "debug": ansi.Magenta("debug "), // info has no prefix "ok": ansi.Bold(ansi.Green("ok ")), "warning": ansi.Bold(ansi.Yellow("warning ")), "fatal": ansi.Bold(ansi.Red("fatal ")), } } }
func shell(fwdChan chan<- conf.ForwardLine, cfg *conf.Config, dialer Dialer) { help := func() { infoln("Available commands:") infoln(" help, ? - show help") infoln(" quit, ^D - stop forwarding and exit") infoln(" test - test each forward for connection") infoln(" stat - show forwarding statistics") infoln(" debug - enable debugging") infoln(" fwd srcip:srcport dstip:dstport - add forward") } term := liner.NewLiner() atExit(func() { term.Close() }) // Receive commands commands := make(chan string) next := make(chan bool) go func() { for { prompt := "mole> " if debugEnabled { prompt = "(debug) mole> " } cmd, err := term.Prompt(prompt) if err == io.EOF { fmt.Println("quit") commands <- "quit" return } if cmd != "" { commands <- cmd term.AppendHistory(cmd) _, ok := <-next if !ok { return } } } }() // Catch ^C and treat as "quit" command sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, os.Interrupt) go func() { <-sigchan fmt.Println("quit") commands <- "quit" }() // Handle commands for { cmd := <-commands parts := strings.SplitN(cmd, " ", -1) switch parts[0] { case "quit": close(next) return case "help", "?": help() case "stat": printStats() case "test": results := testForwards(dialer, cfg) for res := range results { infof(ansi.Bold(ansi.Cyan(res.name))) for _, line := range res.results { if line.err == nil { infof("%22s %s in %.02f ms", line.dst, ansi.Bold(ansi.Green("-ok-")), line.ms) } else { infof("%22s %s in %.02f ms (%s)", line.dst, ansi.Bold(ansi.Red("fail")), line.ms, line.err) } } } case "debug": infoln(msgDebugEnabled) debugEnabled = true case "fwd": if len(parts) != 3 { warnf(msgErrIncorrectFwd, cmd) break } src := strings.SplitN(parts[1], ":", 2) if len(src) != 2 { warnf(msgErrIncorrectFwdSrc, parts[1]) break } var ipExists bool for _, ip := range currentAddresses() { if ip == src[0] { ipExists = true break } } if !ipExists { warnf(msgErrIncorrectFwdIP, src[0]) break } dst := strings.SplitN(parts[2], ":", 2) if len(dst) != 2 { warnf(msgErrIncorrectFwdDst, parts[2]) break } srcp, err := strconv.Atoi(src[1]) if err != nil { warnln(err) break } if srcp < 1024 { warnf(msgErrIncorrectFwdPriv, srcp) break } dstp, err := strconv.Atoi(dst[1]) if err != nil { warnln(err) break } fwd := conf.ForwardLine{ SrcIP: src[0], SrcPort: srcp, DstIP: dst[0], DstPort: dstp, } okln("add", fwd) fwdChan <- fwd default: warnf(msgErrNoSuchCommand, parts[0]) } next <- true } }