]> Cypherpunks.ru repositories - netrc.git/blob - netrc.go
Initial commit
[netrc.git] / netrc.go
1 // netrc -- parse .netrc file
2 // Copyright 2018 The Go Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 // netrc library parses .netrc file. It is copy-paste of
7 // golang.org/x/tools/cmd/auth/netrcauth.
8 //
9 // See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
10 // for documentation on the .netrc format.
11 package netrc
12
13 import (
14         "os"
15         "path"
16         "strings"
17 )
18
19 type Line struct {
20         Machine  string
21         Login    string
22         Password string
23 }
24
25 func Parse(data string) []Line {
26         var nrc []Line
27         var l Line
28         inMacro := false
29         for _, line := range strings.Split(data, "\n") {
30                 if inMacro {
31                         if line == "" {
32                                 inMacro = false
33                         }
34                         continue
35                 }
36                 f := strings.Fields(line)
37                 i := 0
38                 for ; i < len(f)-1; i += 2 {
39                         // Reset at each "machine" token.
40                         // "The auto-login process searches the .netrc file for a machine token
41                         // that matches […]. Once a match is made, the subsequent .netrc tokens
42                         // are processed, stopping when the end of file is reached or another
43                         // machine or a default token is encountered."
44                         switch f[i] {
45                         case "machine":
46                                 l = Line{Machine: f[i+1]}
47                         case "default":
48                                 break
49                         case "login":
50                                 l.Login = f[i+1]
51                         case "password":
52                                 l.Password = f[i+1]
53                         case "macdef":
54                                 // "A macro is defined with the specified name; its contents begin with
55                                 // the next .netrc line and continue until a null line (consecutive
56                                 // new-line characters) is encountered."
57                                 inMacro = true
58                         }
59                         if l.Machine != "" && l.Login != "" && l.Password != "" {
60                                 nrc = append(nrc, l)
61                                 l = Line{}
62                         }
63                 }
64                 if i < len(f) && f[i] == "default" {
65                         // "There can be only one default token, and it must be after all machine tokens."
66                         break
67                 }
68         }
69         return nrc
70 }
71
72 func Path() (netrc string) {
73         p, ok := os.LookupEnv("NETRC")
74         if ok {
75                 return p
76         }
77         homeDir, _ := os.UserHomeDir()
78         return path.Join(homeDir, ".netrc")
79 }
80
81 func Find(host string) (login string, password string) {
82         data, err := os.ReadFile(Path())
83         if err != nil {
84                 return "", ""
85         }
86         for _, l := range Parse(string(data)) {
87                 if l.Machine == host {
88                         return l.Login, l.Password
89                 }
90         }
91         return "", ""
92 }