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