// Package sshconf lit ~/.ssh/config (jamais modifié) pour proposer
// d'importer les hosts existants dans sssh.
package sshconf
import (
"os"
"path/filepath"
"strconv"
"strings"
ssh_config "github.com/kevinburke/ssh_config"
"git.neuromancer.ovh/bastien-mrq/sssh/internal/host"
)
// Hosts rend les alias concrets (sans jokers) déclarés dans ~/.ssh/config.
// Toute erreur de lecture ou de parsing donne une liste vide : ce fichier
// n'appartient pas à sssh, on ne bloque jamais dessus.
func Hosts() []host.Host {
home, err := os.UserHomeDir()
if err != nil {
return nil
}
f, err := os.Open(filepath.Join(home, ".ssh", "config"))
if err != nil {
return nil
}
defer f.Close()
cfg, err := ssh_config.Decode(f)
if err != nil {
return nil
}
var hosts []host.Host
for _, block := range cfg.Hosts {
kv := map[string]string{}
for _, node := range block.Nodes {
if n, ok := node.(*ssh_config.KV); ok {
kv[strings.ToLower(n.Key)] = n.Value
}
}
for _, p := range block.Patterns {
name := p.String()
if strings.ContainsAny(name, "*?!") {
continue
}
h := host.Host{Name: name}
h.Host = kv["hostname"]
if h.Host == "" {
h.Host = name
}
h.User = kv["user"]
if v := kv["port"]; v != "" {
h.Port, _ = strconv.Atoi(v)
}
h.Identity = kv["identityfile"]
h.Jump = kv["proxyjump"]
hosts = append(hosts, h)
}
}
return hosts
}