func TestHostSection(t *testing.T) { hostSection := `# Some example Host section Host local # Local SSH OptionOne do anything here OptionTwo 12345 # There is also a comment OptionWithoutValue OptionsWithComment # Comment ` sections, err := sshconfig.Parse(reader(hostSection)) if err != nil { t.Fatal(err) } if len(sections) != 1 { t.Error("Unexpected number of sections") } s0 := sections[0] if s0.Name != "local" { t.Error("Unexpected section name") } if s0.Values["OptionOne"] != "do anything here" { t.Error("Unexpected option value (composite string)") } if s0.Values["OptionTwo"] != "12345" { t.Error("Unexpected option value (numeric)") } if v, ok := s0.Values["OptionWithoutValue"]; !ok || v != "" { t.Error("Unexpected value for option without value, or not parsed") } if v, ok := s0.Values["OptionsWithComment"]; !ok || v != "" { t.Error("Unexpected value for option without value, or not parsed") } }
func parseCmdLine() (key, username, addr string, interval time.Duration) { ok, arg, args := shift(os.Args) var argKey, argHost, argInt string for ok { ok, arg, args = shift(args) if !ok { break } if arg == "-h" || arg == "--help" || arg == "--version" { usage(0) } if arg == "-i" { ok, argKey, args = shift(args) if !ok { usage(1) } } else if len(argHost) == 0 { argHost = arg } else if len(argInt) == 0 { argInt = arg } else { usage(1) } } if len(argHost) == 0 || argHost[0] == '-' { usage(1) } // key usr, err := user.Current() if err != nil { log.Print(err) usage(1) } f, err := os.Open(filepath.Join(usr.HomeDir, ".ssh", "config")) // Got the config, scan for matching hosts if err == nil { sections, err := sshconfig.Parse(f) if err != nil { log.Printf("error parsing ssh config: %v", err) } else { for s := range sections { // Support multiple definitions per config entry hostnames := strings.Split(sections[s].Name, " ") for _, h := range hostnames { // Choose ssh config entry values if they exist if h == argHost { configHostname, ok := sections[s].Values["Hostname"] if ok { argHost = configHostname } configUser, ok := sections[s].Values["User"] if ok { username = configUser } configPort, ok := sections[s].Values["Port"] if ok { argHost = fmt.Sprintf("%v:%v", argHost, configPort) } } } } } } if len(argKey) == 0 { key = filepath.Join(usr.HomeDir, ".ssh", "id_rsa") if _, err := os.Stat(key); os.IsNotExist(err) { key = "" } } else { key = argKey } // username, addr if i := strings.Index(argHost, "@"); i != -1 { username = argHost[:i] if i+1 >= len(argHost) { usage(1) } addr = argHost[i+1:] } else { username = usr.Username addr = argHost } if i := strings.Index(addr, ":"); i == -1 { addr += ":22" } // interval if len(argInt) == 0 { interval = DEFAULT_REFRESH * time.Second } else { i, err := strconv.ParseUint(argInt, 10, 64) if err != nil { log.Print(err) usage(1) } interval = time.Duration(i) * time.Second } return }