Function bodies 51 total
ssh_config.homedir function · go · L63-L70 (8 LOC)config.go
func homedir() string {
user, err := osuser.Current()
if err == nil {
return user.HomeDir
} else {
return os.Getenv("HOME")
}
}ssh_config.findVal function · go · L89-L101 (13 LOC)config.go
func findVal(c *Config, alias, key string) (string, error) {
if c == nil {
return "", nil
}
val, err := c.Get(alias, key)
if err != nil || val == "" {
return "", err
}
if err := validate(key, val); err != nil {
return "", err
}
return val, nil
}ssh_config.findAll function · go · L103-L108 (6 LOC)config.go
func findAll(c *Config, alias, key string) ([]string, error) {
if c == nil {
return nil, nil
}
return c.GetAll(alias, key)
}ssh_config.UserSettings.Get method · go · L173-L179 (7 LOC)config.go
func (u *UserSettings) Get(alias, key string) string {
val, err := u.GetStrict(alias, key)
if err != nil {
return ""
}
return val
}ssh_config.UserSettings.GetStrict method · go · L199-L221 (23 LOC)config.go
func (u *UserSettings) GetStrict(alias, key string) (string, error) {
u.doLoadConfigs()
//lint:ignore S1002 I prefer it this way
if u.onceErr != nil && u.IgnoreErrors == false {
return "", u.onceErr
}
// TODO this is getting repetitive
if u.customConfig != nil {
val, err := findVal(u.customConfig, alias, key)
if err != nil || val != "" {
return val, err
}
}
val, err := findVal(u.userConfig, alias, key)
if err != nil || val != "" {
return val, err
}
val2, err2 := findVal(u.systemConfig, alias, key)
if err2 != nil || val2 != "" {
return val2, err2
}
return Default(key), nil
}ssh_config.UserSettings.GetAllStrict method · go · L231-L256 (26 LOC)config.go
func (u *UserSettings) GetAllStrict(alias, key string) ([]string, error) {
u.doLoadConfigs()
//lint:ignore S1002 I prefer it this way
if u.onceErr != nil && u.IgnoreErrors == false {
return nil, u.onceErr
}
if u.customConfig != nil {
val, err := findAll(u.customConfig, alias, key)
if err != nil || val != nil {
return val, err
}
}
val, err := findAll(u.userConfig, alias, key)
if err != nil || val != nil {
return val, err
}
val2, err2 := findAll(u.systemConfig, alias, key)
if err2 != nil || val2 != nil {
return val2, err2
}
// TODO: IdentityFile has multiple default values that we should return.
if def := Default(key); def != "" {
return []string{def}, nil
}
return []string{}, nil
}ssh_config.UserSettings.ConfigFinder method · go · L264-L269 (6 LOC)config.go
func (u *UserSettings) ConfigFinder(f func() string) {
if f == nil {
panic("cannot call ConfigFinder with nil function")
}
u.customConfigFinder = f
}Same scanner, your repo: https://repobility.com — Repobility
ssh_config.UserSettings.doLoadConfigs method · go · L271-L308 (38 LOC)config.go
func (u *UserSettings) doLoadConfigs() {
u.loadConfigs.Do(func() {
var filename string
var err error
if u.customConfigFinder != nil {
filename = u.customConfigFinder()
u.customConfig, err = parseFile(filename)
// IsNotExist should be returned because a user specified this
// function - not existing likely means they made an error
if err != nil {
u.onceErr = err
}
return
}
if u.userConfigFinder == nil {
filename = userConfigFinder()
} else {
filename = u.userConfigFinder()
}
u.userConfig, err = parseFile(filename)
//lint:ignore S1002 I prefer it this way
if err != nil && os.IsNotExist(err) == false {
u.onceErr = err
return
}
if u.systemConfigFinder == nil {
filename = systemConfigFinder()
} else {
filename = u.systemConfigFinder()
}
u.systemConfig, err = parseFile(filename)
//lint:ignore S1002 I prefer it this way
if err != nil && os.IsNotExist(err) == false {
u.onceErr = err
return
}
})
}ssh_config.parseWithDepth function · go · L314-L320 (7 LOC)config.go
func parseWithDepth(filename string, depth uint8) (*Config, error) {
b, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
return decodeBytes(b, isSystem(filename), depth)
}ssh_config.Decode function · go · L329-L335 (7 LOC)config.go
func Decode(r io.Reader) (*Config, error) {
b, err := io.ReadAll(r)
if err != nil {
return nil, err
}
return decodeBytes(b, false, 0)
}ssh_config.decodeBytes function · go · L343-L359 (17 LOC)config.go
func decodeBytes(b []byte, system bool, depth uint8) (c *Config, err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
if e, ok := r.(error); ok && e == ErrDepthExceeded {
err = e
return
}
err = errors.New(r.(string))
}
}()
c = parseSSH(lexSSH(b), system, depth)
return c, err
}ssh_config.Config.Get method · go · L375-L402 (28 LOC)config.go
func (c *Config) Get(alias, key string) (string, error) {
lowerKey := strings.ToLower(key)
for _, host := range c.Hosts {
if !host.Matches(alias) {
continue
}
for _, node := range host.Nodes {
switch t := node.(type) {
case *Empty:
continue
case *KV:
// "keys are case insensitive" per the spec
lkey := strings.ToLower(t.Key)
if lkey == lowerKey {
return t.Value, nil
}
case *Include:
val := t.Get(alias, key)
if val != "" {
return val, nil
}
default:
return "", fmt.Errorf("unknown Node type %v", t)
}
}
}
return "", nil
}ssh_config.Config.GetAll method · go · L406-L435 (30 LOC)config.go
func (c *Config) GetAll(alias, key string) ([]string, error) {
lowerKey := strings.ToLower(key)
all := []string(nil)
for _, host := range c.Hosts {
if !host.Matches(alias) {
continue
}
for _, node := range host.Nodes {
switch t := node.(type) {
case *Empty:
continue
case *KV:
// "keys are case insensitive" per the spec
lkey := strings.ToLower(t.Key)
if lkey == lowerKey {
all = append(all, t.Value)
}
case *Include:
val, _ := t.GetAll(alias, key)
if len(val) > 0 {
all = append(all, val...)
}
default:
return nil, fmt.Errorf("unknown Node type %v", t)
}
}
}
return all, nil
}ssh_config.marshal function · go · L446-L452 (7 LOC)config.go
func marshal(c Config) *bytes.Buffer {
var buf bytes.Buffer
for i := range c.Hosts {
buf.WriteString(c.Hosts[i].String())
}
return &buf
}ssh_config.Pattern.String method · go · L463-L468 (6 LOC)config.go
func (p Pattern) String() string {
if p.not {
return "!" + p.str
}
return p.str
}Repobility · code-quality intelligence platform · https://repobility.com
ssh_config.NewPattern function · go · L491-L523 (33 LOC)config.go
func NewPattern(s string) (*Pattern, error) {
if s == "" {
return nil, errors.New("ssh_config: empty pattern")
}
negated := false
if s[0] == '!' {
negated = true
s = s[1:]
}
var buf bytes.Buffer
buf.WriteByte('^')
for i := 0; i < len(s); i++ {
// A byte loop is correct because all metacharacters are ASCII.
switch b := s[i]; b {
case '*':
buf.WriteString(".*")
case '?':
buf.WriteString(".?")
default:
// borrowing from QuoteMeta here.
if special(b) {
buf.WriteByte('\\')
}
buf.WriteByte(b)
}
}
buf.WriteByte('$')
r, err := regexp.Compile(buf.String())
if err != nil {
return nil, err
}
return &Pattern{str: s, regex: r, not: negated}, nil
}ssh_config.Host.Matches method · go · L550-L567 (18 LOC)config.go
func (h *Host) Matches(alias string) bool {
found := false
for i := range h.Patterns {
if h.Patterns[i].regex.MatchString(alias) {
if h.Patterns[i].not {
// Negated match. "A pattern entry may be negated by prefixing
// it with an exclamation mark (`!'). If a negated entry is
// matched, then the Host entry is ignored, regardless of
// whether any other patterns on the line match. Negated matches
// are therefore useful to provide exceptions for wildcard
// matches."
return false
}
found = true
}
}
return found
}ssh_config.Host.String method · go · L571-L623 (53 LOC)config.go
func (h *Host) String() string {
var buf strings.Builder
//lint:ignore S1002 I prefer to write it this way
if h.implicit == false {
buf.WriteString(strings.Repeat(" ", int(h.leadingSpace)))
if h.isMatch {
buf.WriteString("Match")
if h.hasEquals {
buf.WriteString(" = ")
} else {
buf.WriteString(" ")
}
buf.WriteString(h.matchKeyword)
if !strings.EqualFold(h.matchKeyword, "all") {
buf.WriteString(" ")
for i, pat := range h.Patterns {
buf.WriteString(pat.String())
if i < len(h.Patterns)-1 {
buf.WriteString(" ")
}
}
}
} else {
buf.WriteString("Host")
if h.hasEquals {
buf.WriteString(" = ")
} else {
buf.WriteString(" ")
}
for i, pat := range h.Patterns {
buf.WriteString(pat.String())
if i < len(h.Patterns)-1 {
buf.WriteString(" ")
}
}
}
if h.EOLComment != "" {
if h.spaceBeforeComment != "" {
buf.WriteString(h.spaceBeforeComment)
} else {
buf.WriteByte(' ')
}
ssh_config.KV.String method · go · L653-L677 (25 LOC)config.go
func (k *KV) String() string {
if k == nil {
return ""
}
equals := " "
if k.hasEquals {
equals = " = "
}
val := k.Value
if k.rawValue != "" {
val = k.rawValue
}
line := strings.Repeat(" ", int(k.leadingSpace)) + k.Key + equals + val
if k.Comment != "" {
if k.spaceAfterValue != "" {
line += k.spaceAfterValue
} else {
line += " "
}
line += "#" + k.Comment
} else {
line += k.spaceAfterValue
}
return line
}ssh_config.Empty.String method · go · L692-L700 (9 LOC)config.go
func (e *Empty) String() string {
if e == nil {
return ""
}
if e.Comment == "" {
return ""
}
return fmt.Sprintf("%s#%s", strings.Repeat(" ", int(e.leadingSpace)), e.Comment)
}ssh_config.removeDups function · go · L731-L744 (14 LOC)config.go
func removeDups(arr []string) []string {
// Use map to record duplicates as we find them.
encountered := make(map[string]bool, len(arr))
result := make([]string, 0)
for v := range arr {
//lint:ignore S1002 I prefer it this way
if encountered[arr[v]] == false {
encountered[arr[v]] = true
result = append(result, arr[v])
}
}
return result
}ssh_config.NewInclude function · go · L750-L792 (43 LOC)config.go
func NewInclude(directives []string, hasEquals bool, pos Position, comment string, system bool, depth uint8) (*Include, error) {
if depth > maxRecurseDepth {
return nil, ErrDepthExceeded
}
inc := &Include{
Comment: comment,
directives: directives,
files: make(map[string]*Config),
position: pos,
leadingSpace: pos.Col - 1,
depth: depth,
hasEquals: hasEquals,
}
// no need for inc.mu.Lock() since nothing else can access this inc
matches := make([]string, 0)
for i := range directives {
var path string
if filepath.IsAbs(directives[i]) {
path = directives[i]
} else if system {
path = filepath.Join("/etc/ssh", directives[i])
} else if strings.HasPrefix(directives[i], "~/") {
path = filepath.Join(homedir(), directives[i][2:])
} else {
path = filepath.Join(homedir(), ".ssh", directives[i])
}
theseMatches, err := filepath.Glob(path)
if err != nil {
return nil, err
}
matches = append(matches, theseMatches...)
}
ssh_config.Include.Get method · go · L801-L816 (16 LOC)config.go
func (inc *Include) Get(alias, key string) string {
inc.mu.Lock()
defer inc.mu.Unlock()
// TODO: we search files in any order which is not correct
for i := range inc.matches {
cfg := inc.files[inc.matches[i]]
if cfg == nil {
panic("nil cfg")
}
val, err := cfg.Get(alias, key)
if err == nil && val != "" {
return val
}
}
return ""
}All rows scored by the Repobility analyzer (https://repobility.com)
ssh_config.Include.GetAll method · go · L820-L841 (22 LOC)config.go
func (inc *Include) GetAll(alias, key string) ([]string, error) {
inc.mu.Lock()
defer inc.mu.Unlock()
var vals []string
// TODO: we search files in any order which is not correct
for i := range inc.matches {
cfg := inc.files[inc.matches[i]]
if cfg == nil {
panic("nil cfg")
}
val, err := cfg.GetAll(alias, key)
if err == nil && len(val) != 0 {
// In theory if SupportsMultiple was false for this key we could
// stop looking here. But the caller has asked us to find all
// instances of the keyword (and could use Get() if they wanted) so
// let's keep looking.
vals = append(vals, val...)
}
}
return vals, nil
}ssh_config.Include.String method · go · L845-L855 (11 LOC)config.go
func (inc *Include) String() string {
equals := " "
if inc.hasEquals {
equals = " = "
}
line := fmt.Sprintf("%sInclude%s%s", strings.Repeat(" ", int(inc.leadingSpace)), equals, strings.Join(inc.directives, " "))
if inc.Comment != "" {
line += " #" + inc.Comment
}
return line
}ssh_config.init function · go · L859-L865 (7 LOC)config.go
func init() {
var err error
matchAll, err = NewPattern("*")
if err != nil {
panic(err)
}
}ssh_config.newConfig function · go · L867-L878 (12 LOC)config.go
func newConfig() *Config {
return &Config{
Hosts: []*Host{
{
implicit: true,
Patterns: []*Pattern{matchAll},
Nodes: make([]Node, 0),
},
},
depth: 0,
}
}ssh_config.sshLexer.lexComment method · go · L22-L36 (15 LOC)lexer.go
func (s *sshLexer) lexComment(previousState sshLexStateFn) sshLexStateFn {
return func() sshLexStateFn {
growingString := ""
for next := s.peek(); next != '\n' && next != eof; next = s.peek() {
if next == '\r' && s.follow("\r\n") {
break
}
growingString += string(next)
s.next()
}
s.emitWithValue(tokenComment, growingString)
s.skip()
return previousState
}
}ssh_config.sshLexer.lexRspace method · go · L39-L48 (10 LOC)lexer.go
func (s *sshLexer) lexRspace() sshLexStateFn {
for {
next := s.peek()
if !isSpace(next) {
break
}
s.skip()
}
return s.lexRvalue
}ssh_config.sshLexer.lexEquals method · go · L50-L65 (16 LOC)lexer.go
func (s *sshLexer) lexEquals() sshLexStateFn {
for {
next := s.peek()
if next == '=' {
s.emit(tokenEquals)
s.skip()
return s.lexRspace
}
// TODO error handling here; newline eof etc.
if !isSpace(next) {
break
}
s.skip()
}
return s.lexRvalue
}ssh_config.sshLexer.lexKey method · go · L67-L82 (16 LOC)lexer.go
func (s *sshLexer) lexKey() sshLexStateFn {
growingString := ""
for r := s.peek(); isKeyChar(r); r = s.peek() {
// simplified a lot here
if isSpace(r) || r == '=' {
s.emitWithValue(tokenKey, growingString)
s.skip()
return s.lexEquals
}
growingString += string(r)
s.next()
}
s.emitWithValue(tokenKey, growingString)
return s.lexEquals
}About: code-quality intelligence by Repobility · https://repobility.com
ssh_config.sshLexer.lexRvalue method · go · L84-L114 (31 LOC)lexer.go
func (s *sshLexer) lexRvalue() sshLexStateFn {
growingString := ""
for {
next := s.peek()
switch next {
case '\r':
if s.follow("\r\n") {
s.emitWithValue(tokenString, growingString)
s.skip()
return s.lexVoid
}
case '\n':
s.emitWithValue(tokenString, growingString)
s.skip()
return s.lexVoid
case '#':
s.emitWithValue(tokenString, growingString)
s.skip()
return s.lexComment(s.lexVoid)
case eof:
s.next()
}
if next == eof {
break
}
growingString += string(next)
s.next()
}
s.emit(tokenEOF)
return nil
}ssh_config.sshLexer.read method · go · L116-L126 (11 LOC)lexer.go
func (s *sshLexer) read() rune {
r := s.peek()
if r == '\n' {
s.endbufferLine++
s.endbufferCol = 1
} else {
s.endbufferCol++
}
s.inputIdx++
return r
}ssh_config.sshLexer.next method · go · L128-L135 (8 LOC)lexer.go
func (s *sshLexer) next() rune {
r := s.read()
if r != eof {
s.buffer = append(s.buffer, r)
}
return r
}ssh_config.sshLexer.lexVoid method · go · L137-L170 (34 LOC)lexer.go
func (s *sshLexer) lexVoid() sshLexStateFn {
for {
next := s.peek()
switch next {
case '#':
s.skip()
return s.lexComment(s.lexVoid)
case '\r':
fallthrough
case '\n':
s.emit(tokenEmptyLine)
s.skip()
continue
}
if isSpace(next) {
s.skip()
}
if isKeyStartChar(next) {
return s.lexKey
}
// removed IsKeyStartChar and lexKey. probably will need to readd
if next == eof {
s.next()
break
}
}
s.emit(tokenEOF)
return nil
}ssh_config.sshLexer.emitWithValue method · go · L187-L195 (9 LOC)lexer.go
func (s *sshLexer) emitWithValue(t tokenType, value string) {
tok := token{
Position: Position{s.line, s.col},
typ: t,
val: value,
}
s.tokens <- tok
s.ignore()
}ssh_config.sshLexer.peek method · go · L197-L204 (8 LOC)lexer.go
func (s *sshLexer) peek() rune {
if s.inputIdx >= len(s.input) {
return eof
}
r := s.input[s.inputIdx]
return r
}ssh_config.sshLexer.follow method · go · L206-L219 (14 LOC)lexer.go
func (s *sshLexer) follow(next string) bool {
inputIdx := s.inputIdx
for _, expectedRune := range next {
if inputIdx >= len(s.input) {
return false
}
r := s.input[inputIdx]
inputIdx++
if expectedRune != r {
return false
}
}
return true
}ssh_config.sshLexer.run method · go · L221-L226 (6 LOC)lexer.go
func (s *sshLexer) run() {
for state := s.lexVoid; state != nil; {
state = state()
}
close(s.tokens)
}Same scanner, your repo: https://repobility.com — Repobility
ssh_config.lexSSH function · go · L228-L240 (13 LOC)lexer.go
func lexSSH(input []byte) chan token {
runes := bytes.Runes(input)
l := &sshLexer{
input: runes,
tokens: make(chan token),
line: 1,
col: 1,
endbufferLine: 1,
endbufferCol: 1,
}
go l.run()
return l.tokens
}ssh_config.sshParser.raiseError method · go · L29-L35 (7 LOC)parser.go
func (p *sshParser) raiseError(tok *token, err error) {
if err == ErrDepthExceeded {
panic(err)
}
// TODO this format is ugly
panic(tok.Position.String() + ": " + err.Error())
}ssh_config.sshParser.peek method · go · L43-L54 (12 LOC)parser.go
func (p *sshParser) peek() *token {
if len(p.tokensBuffer) != 0 {
return &(p.tokensBuffer[0])
}
tok, ok := <-p.flow
if !ok {
return nil
}
p.tokensBuffer = append(p.tokensBuffer, tok)
return &tok
}ssh_config.sshParser.getToken method · go · L56-L67 (12 LOC)parser.go
func (p *sshParser) getToken() *token {
if len(p.tokensBuffer) != 0 {
tok := p.tokensBuffer[0]
p.tokensBuffer = p.tokensBuffer[1:]
return &tok
}
tok, ok := <-p.flow
if !ok {
return nil
}
return &tok
}ssh_config.sshParser.parseStart method · go · L69-L88 (20 LOC)parser.go
func (p *sshParser) parseStart() sshParserStateFn {
tok := p.peek()
// end of stream, parsing is finished
if tok == nil {
return nil
}
switch tok.typ {
case tokenComment, tokenEmptyLine:
return p.parseComment
case tokenKey:
return p.parseKV
case tokenEOF:
return nil
default:
p.raiseErrorf(tok, fmt.Sprintf("unexpected token %q\n", tok))
}
return nil
}ssh_config.sshParser.parseKV method · go · L90-L169 (80 LOC)parser.go
func (p *sshParser) parseKV() sshParserStateFn {
key := p.getToken()
hasEquals := false
val := p.getToken()
if val.typ == tokenEquals {
hasEquals = true
val = p.getToken()
}
comment := ""
tok := p.peek()
if tok == nil {
tok = &token{typ: tokenEOF}
}
if tok.typ == tokenComment && tok.Position.Line == val.Position.Line {
tok = p.getToken()
comment = tok.val
}
if strings.ToLower(key.val) == "match" {
return p.parseMatch(val, hasEquals, comment)
}
if strings.ToLower(key.val) == "host" {
strPatterns := strings.Split(val.val, " ")
patterns := make([]*Pattern, 0)
for i := range strPatterns {
if strPatterns[i] == "" {
continue
}
pat, err := NewPattern(strPatterns[i])
if err != nil {
p.raiseErrorf(val, fmt.Sprintf("Invalid host pattern: %v", err))
return nil
}
patterns = append(patterns, pat)
}
// val.val at this point could be e.g. "example.com "
hostval := strings.TrimRightFunc(val.val, unicode.IsSpace)
spaceBeforeComssh_config.sshParser.parseMatch method · go · L171-L236 (66 LOC)parser.go
func (p *sshParser) parseMatch(val *token, hasEquals bool, comment string) sshParserStateFn {
// val.val contains everything after "Match ", e.g. "Host *.example.com"
// or "all".
trimmed := strings.TrimRightFunc(val.val, unicode.IsSpace)
spaceBeforeComment := val.val[len(trimmed):]
fields := strings.Fields(trimmed)
if len(fields) == 0 {
p.raiseErrorf(val, "ssh_config: Match directive requires at least one criterion")
return nil
}
criterion := strings.ToLower(fields[0])
switch criterion {
case "all":
// "Match all" is equivalent to "Host *" — matches everything.
p.config.Hosts = append(p.config.Hosts, &Host{
Patterns: []*Pattern{matchAll},
Nodes: make([]Node, 0),
EOLComment: comment,
spaceBeforeComment: spaceBeforeComment,
hasEquals: hasEquals,
isMatch: true,
matchKeyword: fields[0], // preserve original case
})
return p.parseStart
case "host":
patterns := make([]*Pattern, 0)
for ssh_config.sshParser.parseComment method · go · L238-L248 (11 LOC)parser.go
func (p *sshParser) parseComment() sshParserStateFn {
comment := p.getToken()
lastHost := p.config.Hosts[len(p.config.Hosts)-1]
lastHost.Nodes = append(lastHost.Nodes, &Empty{
Comment: comment.val,
// account for the "#" as well
leadingSpace: comment.Position.Col - 2,
position: comment.Position,
})
return p.parseStart
}Repobility · code-quality intelligence platform · https://repobility.com
ssh_config.parseSSH function · go · L250-L270 (21 LOC)parser.go
func parseSSH(flow chan token, system bool, depth uint8) *Config {
// Ensure we consume tokens to completion even if parser exits early
defer func() {
for range flow {
}
}()
result := newConfig()
result.position = Position{1, 1}
parser := &sshParser{
flow: flow,
config: result,
tokensBuffer: make([]token, 0),
currentTable: make([]string, 0),
seenTableKeys: make([]string, 0),
system: system,
depth: depth,
}
parser.run()
return result
}ssh_config.token.String method · go · L11-L17 (7 LOC)token.go
func (t token) String() string {
switch t.typ {
case tokenEOF:
return "EOF"
}
return fmt.Sprintf("%q", t.val)
}ssh_config.isKeyChar function · go · L44-L49 (6 LOC)token.go
func isKeyChar(r rune) bool {
// Keys start with the first character that isn't whitespace or [ and end
// with the last non-whitespace character before the equals sign. Keys
// cannot contain a # character."
return !(r == '\r' || r == '\n' || r == eof || r == '=')
}page 1 / 2next ›