Daily bump.
[official-gcc.git] / libgo / go / net / nss.go
blob08c3e6a69fe55f7ca774e987bf9fcf571e623407
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
7 package net
9 import (
10 "errors"
11 "io"
12 "os"
15 // nssConf represents the state of the machine's /etc/nsswitch.conf file.
16 type nssConf struct {
17 err error // any error encountered opening or parsing the file
18 sources map[string][]nssSource // keyed by database (e.g. "hosts")
21 type nssSource struct {
22 source string // e.g. "compat", "files", "mdns4_minimal"
23 criteria []nssCriterion
26 // standardCriteria reports all specified criteria have the default
27 // status actions.
28 func (s nssSource) standardCriteria() bool {
29 for i, crit := range s.criteria {
30 if !crit.standardStatusAction(i == len(s.criteria)-1) {
31 return false
34 return true
37 // nssCriterion is the parsed structure of one of the criteria in brackets
38 // after an NSS source name.
39 type nssCriterion struct {
40 negate bool // if "!" was present
41 status string // e.g. "success", "unavail" (lowercase)
42 action string // e.g. "return", "continue" (lowercase)
45 // standardStatusAction reports whether c is equivalent to not
46 // specifying the criterion at all. last is whether this criteria is the
47 // last in the list.
48 func (c nssCriterion) standardStatusAction(last bool) bool {
49 if c.negate {
50 return false
52 var def string
53 switch c.status {
54 case "success":
55 def = "return"
56 case "notfound", "unavail", "tryagain":
57 def = "continue"
58 default:
59 // Unknown status
60 return false
62 if last && c.action == "return" {
63 return true
65 return c.action == def
68 func parseNSSConfFile(file string) *nssConf {
69 f, err := os.Open(file)
70 if err != nil {
71 return &nssConf{err: err}
73 defer f.Close()
74 return parseNSSConf(f)
77 func parseNSSConf(r io.Reader) *nssConf {
78 slurp, err := readFull(r)
79 if err != nil {
80 return &nssConf{err: err}
82 conf := new(nssConf)
83 conf.err = foreachLine(slurp, func(line []byte) error {
84 line = trimSpace(removeComment(line))
85 if len(line) == 0 {
86 return nil
88 colon := bytesIndexByte(line, ':')
89 if colon == -1 {
90 return errors.New("no colon on line")
92 db := string(trimSpace(line[:colon]))
93 srcs := line[colon+1:]
94 for {
95 srcs = trimSpace(srcs)
96 if len(srcs) == 0 {
97 break
99 sp := bytesIndexByte(srcs, ' ')
100 var src string
101 if sp == -1 {
102 src = string(srcs)
103 srcs = nil // done
104 } else {
105 src = string(srcs[:sp])
106 srcs = trimSpace(srcs[sp+1:])
108 var criteria []nssCriterion
109 // See if there's a criteria block in brackets.
110 if len(srcs) > 0 && srcs[0] == '[' {
111 bclose := bytesIndexByte(srcs, ']')
112 if bclose == -1 {
113 return errors.New("unclosed criterion bracket")
115 var err error
116 criteria, err = parseCriteria(srcs[1:bclose])
117 if err != nil {
118 return errors.New("invalid criteria: " + string(srcs[1:bclose]))
120 srcs = srcs[bclose+1:]
122 if conf.sources == nil {
123 conf.sources = make(map[string][]nssSource)
125 conf.sources[db] = append(conf.sources[db], nssSource{
126 source: src,
127 criteria: criteria,
130 return nil
132 return conf
135 // parses "foo=bar !foo=bar"
136 func parseCriteria(x []byte) (c []nssCriterion, err error) {
137 err = foreachField(x, func(f []byte) error {
138 not := false
139 if len(f) > 0 && f[0] == '!' {
140 not = true
141 f = f[1:]
143 if len(f) < 3 {
144 return errors.New("criterion too short")
146 eq := bytesIndexByte(f, '=')
147 if eq == -1 {
148 return errors.New("criterion lacks equal sign")
150 lowerASCIIBytes(f)
151 c = append(c, nssCriterion{
152 negate: not,
153 status: string(f[:eq]),
154 action: string(f[eq+1:]),
156 return nil
158 return