101 | 101 |
return val, nil
|
102 | 102 |
}
|
103 | 103 |
|
|
104 |
func findAll(c *Config, alias, key string) ([]string, error) {
|
|
105 |
if c == nil {
|
|
106 |
return nil, nil
|
|
107 |
}
|
|
108 |
return c.GetAll(alias, key)
|
|
109 |
}
|
|
110 |
|
104 | 111 |
// Get finds the first value for key within a declaration that matches the
|
105 | 112 |
// alias. Get returns the empty string if no value was found, or if IgnoreErrors
|
106 | 113 |
// is false and we could not parse the configuration file. Use GetStrict to
|
|
113 | 120 |
return DefaultUserSettings.Get(alias, key)
|
114 | 121 |
}
|
115 | 122 |
|
|
123 |
// GetAll retrieves zero or more directives for key for the given alias. GetAll
|
|
124 |
// returns nil if no value was found, or if IgnoreErrors is false and we could
|
|
125 |
// not parse the configuration file. Use GetAllStrict to disambiguate the
|
|
126 |
// latter cases.
|
|
127 |
//
|
|
128 |
// In most cases you want to use Get or GetStrict, which returns a single value.
|
|
129 |
// However, a subset of ssh configuration values (IdentityFile, for example)
|
|
130 |
// allow you to specify multiple directives.
|
|
131 |
//
|
|
132 |
// The match for key is case insensitive.
|
|
133 |
//
|
|
134 |
// GetAll is a wrapper around DefaultUserSettings.GetAll.
|
|
135 |
func GetAll(alias, key string) []string {
|
|
136 |
return DefaultUserSettings.GetAll(alias, key)
|
|
137 |
}
|
|
138 |
|
116 | 139 |
// GetStrict finds the first value for key within a declaration that matches the
|
117 | 140 |
// alias. If key has a default value and no matching configuration is found, the
|
118 | 141 |
// default will be returned. For more information on default values and the way
|
119 | 142 |
// patterns are matched, see the manpage for ssh_config.
|
120 | 143 |
//
|
121 | |
// error will be non-nil if and only if a user's configuration file or the
|
122 | |
// system configuration file could not be parsed, and u.IgnoreErrors is false.
|
|
144 |
// The returned error will be non-nil if and only if a user's configuration file
|
|
145 |
// or the system configuration file could not be parsed, and u.IgnoreErrors is
|
|
146 |
// false.
|
123 | 147 |
//
|
124 | 148 |
// GetStrict is a wrapper around DefaultUserSettings.GetStrict.
|
125 | 149 |
func GetStrict(alias, key string) (string, error) {
|
126 | 150 |
return DefaultUserSettings.GetStrict(alias, key)
|
|
151 |
}
|
|
152 |
|
|
153 |
// GetAllStrict retrieves zero or more directives for key for the given alias.
|
|
154 |
//
|
|
155 |
// In most cases you want to use Get or GetStrict, which returns a single value.
|
|
156 |
// However, a subset of ssh configuration values (IdentityFile, for example)
|
|
157 |
// allow you to specify multiple directives.
|
|
158 |
//
|
|
159 |
// The returned error will be non-nil if and only if a user's configuration file
|
|
160 |
// or the system configuration file could not be parsed, and u.IgnoreErrors is
|
|
161 |
// false.
|
|
162 |
//
|
|
163 |
// GetAllStrict is a wrapper around DefaultUserSettings.GetAllStrict.
|
|
164 |
func GetAllStrict(alias, key string) ([]string, error) {
|
|
165 |
return DefaultUserSettings.GetAllStrict(alias, key)
|
127 | 166 |
}
|
128 | 167 |
|
129 | 168 |
// Get finds the first value for key within a declaration that matches the
|
|
140 | 179 |
return val
|
141 | 180 |
}
|
142 | 181 |
|
|
182 |
// GetAll retrieves zero or more directives for key for the given alias. GetAll
|
|
183 |
// returns nil if no value was found, or if IgnoreErrors is false and we could
|
|
184 |
// not parse the configuration file. Use GetStrict to disambiguate the latter
|
|
185 |
// cases.
|
|
186 |
//
|
|
187 |
// The match for key is case insensitive.
|
|
188 |
func (u *UserSettings) GetAll(alias, key string) []string {
|
|
189 |
val, _ := u.GetAllStrict(alias, key)
|
|
190 |
return val
|
|
191 |
}
|
|
192 |
|
143 | 193 |
// GetStrict finds the first value for key within a declaration that matches the
|
144 | 194 |
// alias. If key has a default value and no matching configuration is found, the
|
145 | 195 |
// default will be returned. For more information on default values and the way
|
|
148 | 198 |
// error will be non-nil if and only if a user's configuration file or the
|
149 | 199 |
// system configuration file could not be parsed, and u.IgnoreErrors is false.
|
150 | 200 |
func (u *UserSettings) GetStrict(alias, key string) (string, error) {
|
|
201 |
u.doLoadConfigs()
|
|
202 |
//lint:ignore S1002 I prefer it this way
|
|
203 |
if u.onceErr != nil && u.IgnoreErrors == false {
|
|
204 |
return "", u.onceErr
|
|
205 |
}
|
|
206 |
val, err := findVal(u.userConfig, alias, key)
|
|
207 |
if err != nil || val != "" {
|
|
208 |
return val, err
|
|
209 |
}
|
|
210 |
val2, err2 := findVal(u.systemConfig, alias, key)
|
|
211 |
if err2 != nil || val2 != "" {
|
|
212 |
return val2, err2
|
|
213 |
}
|
|
214 |
return Default(key), nil
|
|
215 |
}
|
|
216 |
|
|
217 |
// GetAllStrict retrieves zero or more directives for key for the given alias.
|
|
218 |
// If key has a default value and no matching configuration is found, the
|
|
219 |
// default will be returned. For more information on default values and the way
|
|
220 |
// patterns are matched, see the manpage for ssh_config.
|
|
221 |
//
|
|
222 |
// The returned error will be non-nil if and only if a user's configuration file
|
|
223 |
// or the system configuration file could not be parsed, and u.IgnoreErrors is
|
|
224 |
// false.
|
|
225 |
func (u *UserSettings) GetAllStrict(alias, key string) ([]string, error) {
|
|
226 |
u.doLoadConfigs()
|
|
227 |
//lint:ignore S1002 I prefer it this way
|
|
228 |
if u.onceErr != nil && u.IgnoreErrors == false {
|
|
229 |
return nil, u.onceErr
|
|
230 |
}
|
|
231 |
val, err := findAll(u.userConfig, alias, key)
|
|
232 |
if err != nil || val != nil {
|
|
233 |
return val, err
|
|
234 |
}
|
|
235 |
val2, err2 := findAll(u.systemConfig, alias, key)
|
|
236 |
if err2 != nil || val2 != nil {
|
|
237 |
return val2, err2
|
|
238 |
}
|
|
239 |
// TODO: IdentityFile has multiple default values that we should return.
|
|
240 |
if def := Default(key); def != "" {
|
|
241 |
return []string{def}, nil
|
|
242 |
}
|
|
243 |
return []string{}, nil
|
|
244 |
}
|
|
245 |
|
|
246 |
func (u *UserSettings) doLoadConfigs() {
|
151 | 247 |
u.loadConfigs.Do(func() {
|
152 | 248 |
// can't parse user file, that's ok.
|
153 | 249 |
var filename string
|
|
175 | 271 |
return
|
176 | 272 |
}
|
177 | 273 |
})
|
178 | |
//lint:ignore S1002 I prefer it this way
|
179 | |
if u.onceErr != nil && u.IgnoreErrors == false {
|
180 | |
return "", u.onceErr
|
181 | |
}
|
182 | |
val, err := findVal(u.userConfig, alias, key)
|
183 | |
if err != nil || val != "" {
|
184 | |
return val, err
|
185 | |
}
|
186 | |
val2, err2 := findVal(u.systemConfig, alias, key)
|
187 | |
if err2 != nil || val2 != "" {
|
188 | |
return val2, err2
|
189 | |
}
|
190 | |
return Default(key), nil
|
191 | 274 |
}
|
192 | 275 |
|
193 | 276 |
func parseFile(filename string) (*Config, error) {
|
|
281 | 364 |
return "", nil
|
282 | 365 |
}
|
283 | 366 |
|
|
367 |
// GetAll returns all values in the configuration that match the alias and
|
|
368 |
// contains key, or nil if none are present.
|
|
369 |
func (c *Config) GetAll(alias, key string) ([]string, error) {
|
|
370 |
lowerKey := strings.ToLower(key)
|
|
371 |
all := []string(nil)
|
|
372 |
for _, host := range c.Hosts {
|
|
373 |
if !host.Matches(alias) {
|
|
374 |
continue
|
|
375 |
}
|
|
376 |
for _, node := range host.Nodes {
|
|
377 |
switch t := node.(type) {
|
|
378 |
case *Empty:
|
|
379 |
continue
|
|
380 |
case *KV:
|
|
381 |
// "keys are case insensitive" per the spec
|
|
382 |
lkey := strings.ToLower(t.Key)
|
|
383 |
if lkey == "match" {
|
|
384 |
panic("can't handle Match directives")
|
|
385 |
}
|
|
386 |
if lkey == lowerKey {
|
|
387 |
all = append(all, t.Value)
|
|
388 |
}
|
|
389 |
case *Include:
|
|
390 |
val, _ := t.GetAll(alias, key)
|
|
391 |
if len(val) > 0 {
|
|
392 |
all = append(all, val...)
|
|
393 |
}
|
|
394 |
default:
|
|
395 |
return nil, fmt.Errorf("unknown Node type %v", t)
|
|
396 |
}
|
|
397 |
}
|
|
398 |
}
|
|
399 |
|
|
400 |
return all, nil
|
|
401 |
}
|
|
402 |
|
284 | 403 |
// String returns a string representation of the Config file.
|
285 | 404 |
func (c Config) String() string {
|
286 | 405 |
return marshal(c).String()
|
|
610 | 729 |
return ""
|
611 | 730 |
}
|
612 | 731 |
|
|
732 |
// GetAll finds all values in the Include statement matching the alias and the
|
|
733 |
// given key.
|
|
734 |
func (inc *Include) GetAll(alias, key string) ([]string, error) {
|
|
735 |
inc.mu.Lock()
|
|
736 |
defer inc.mu.Unlock()
|
|
737 |
var vals []string
|
|
738 |
|
|
739 |
// TODO: we search files in any order which is not correct
|
|
740 |
for i := range inc.matches {
|
|
741 |
cfg := inc.files[inc.matches[i]]
|
|
742 |
if cfg == nil {
|
|
743 |
panic("nil cfg")
|
|
744 |
}
|
|
745 |
val, err := cfg.GetAll(alias, key)
|
|
746 |
if err == nil && len(val) != 0 {
|
|
747 |
// In theory if SupportsMultiple was false for this key we could
|
|
748 |
// stop looking here. But the caller has asked us to find all
|
|
749 |
// instances of the keyword (and could use Get() if they wanted) so
|
|
750 |
// let's keep looking.
|
|
751 |
vals = append(vals, val...)
|
|
752 |
}
|
|
753 |
}
|
|
754 |
return vals, nil
|
|
755 |
}
|
|
756 |
|
613 | 757 |
// String prints out a string representation of this Include directive. Note
|
614 | 758 |
// included Config files are not printed as part of this representation.
|
615 | 759 |
func (inc *Include) String() string {
|