...
Source file
src/net/nss.go
Documentation: net
1
2
3
4
5
6
7
8 package net
9
10 import (
11 "errors"
12 "internal/bytealg"
13 "io"
14 "os"
15 )
16
17
18 type nssConf struct {
19 err error
20 sources map[string][]nssSource
21 }
22
23 type nssSource struct {
24 source string
25 criteria []nssCriterion
26 }
27
28
29
30 func (s nssSource) standardCriteria() bool {
31 for i, crit := range s.criteria {
32 if !crit.standardStatusAction(i == len(s.criteria)-1) {
33 return false
34 }
35 }
36 return true
37 }
38
39
40
41 type nssCriterion struct {
42 negate bool
43 status string
44 action string
45 }
46
47
48
49
50 func (c nssCriterion) standardStatusAction(last bool) bool {
51 if c.negate {
52 return false
53 }
54 var def string
55 switch c.status {
56 case "success":
57 def = "return"
58 case "notfound", "unavail", "tryagain":
59 def = "continue"
60 default:
61
62 return false
63 }
64 if last && c.action == "return" {
65 return true
66 }
67 return c.action == def
68 }
69
70 func parseNSSConfFile(file string) *nssConf {
71 f, err := os.Open(file)
72 if err != nil {
73 return &nssConf{err: err}
74 }
75 defer f.Close()
76 return parseNSSConf(f)
77 }
78
79 func parseNSSConf(r io.Reader) *nssConf {
80 slurp, err := readFull(r)
81 if err != nil {
82 return &nssConf{err: err}
83 }
84 conf := new(nssConf)
85 conf.err = foreachLine(slurp, func(line []byte) error {
86 line = trimSpace(removeComment(line))
87 if len(line) == 0 {
88 return nil
89 }
90 colon := bytealg.IndexByte(line, ':')
91 if colon == -1 {
92 return errors.New("no colon on line")
93 }
94 db := string(trimSpace(line[:colon]))
95 srcs := line[colon+1:]
96 for {
97 srcs = trimSpace(srcs)
98 if len(srcs) == 0 {
99 break
100 }
101 sp := bytealg.IndexByte(srcs, ' ')
102 var src string
103 if sp == -1 {
104 src = string(srcs)
105 srcs = nil
106 } else {
107 src = string(srcs[:sp])
108 srcs = trimSpace(srcs[sp+1:])
109 }
110 var criteria []nssCriterion
111
112 if len(srcs) > 0 && srcs[0] == '[' {
113 bclose := bytealg.IndexByte(srcs, ']')
114 if bclose == -1 {
115 return errors.New("unclosed criterion bracket")
116 }
117 var err error
118 criteria, err = parseCriteria(srcs[1:bclose])
119 if err != nil {
120 return errors.New("invalid criteria: " + string(srcs[1:bclose]))
121 }
122 srcs = srcs[bclose+1:]
123 }
124 if conf.sources == nil {
125 conf.sources = make(map[string][]nssSource)
126 }
127 conf.sources[db] = append(conf.sources[db], nssSource{
128 source: src,
129 criteria: criteria,
130 })
131 }
132 return nil
133 })
134 return conf
135 }
136
137
138 func parseCriteria(x []byte) (c []nssCriterion, err error) {
139 err = foreachField(x, func(f []byte) error {
140 not := false
141 if len(f) > 0 && f[0] == '!' {
142 not = true
143 f = f[1:]
144 }
145 if len(f) < 3 {
146 return errors.New("criterion too short")
147 }
148 eq := bytealg.IndexByte(f, '=')
149 if eq == -1 {
150 return errors.New("criterion lacks equal sign")
151 }
152 lowerASCIIBytes(f)
153 c = append(c, nssCriterion{
154 negate: not,
155 status: string(f[:eq]),
156 action: string(f[eq+1:]),
157 })
158 return nil
159 })
160 return
161 }
162
View as plain text