github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/auth/netrc.go (about) 1 // Copyright 2019 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. 4 5 package auth 6 7 import ( 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "runtime" 12 "strings" 13 "sync" 14 ) 15 16 type netrcLine struct { 17 machine string 18 login string 19 password string 20 } 21 22 var ( 23 netrcOnce sync.Once 24 netrc []netrcLine 25 netrcErr error 26 ) 27 28 func parseNetrc(data string) []netrcLine { 29 // See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html 30 // for documentation on the .netrc format. 31 var nrc []netrcLine 32 var l netrcLine 33 inMacro := false 34 for _, line := range strings.Split(data, "\n") { 35 if inMacro { 36 if line == "" { 37 inMacro = false 38 } 39 continue 40 } 41 42 f := strings.Fields(line) 43 i := 0 44 for ; i < len(f)-1; i += 2 { 45 // Reset at each "machine" token. 46 // “The auto-login process searches the .netrc file for a machine token 47 // that matches […]. Once a match is made, the subsequent .netrc tokens 48 // are processed, stopping when the end of file is reached or another 49 // machine or a default token is encountered.” 50 switch f[i] { 51 case "machine": 52 l = netrcLine{machine: f[i+1]} 53 case "default": 54 break 55 case "login": 56 l.login = f[i+1] 57 case "password": 58 l.password = f[i+1] 59 case "macdef": 60 // “A macro is defined with the specified name; its contents begin with 61 // the next .netrc line and continue until a null line (consecutive 62 // new-line characters) is encountered.” 63 inMacro = true 64 } 65 if l.machine != "" && l.login != "" && l.password != "" { 66 nrc = append(nrc, l) 67 l = netrcLine{} 68 } 69 } 70 71 if i < len(f) && f[i] == "default" { 72 // “There can be only one default token, and it must be after all machine tokens.” 73 break 74 } 75 } 76 77 return nrc 78 } 79 80 func netrcPath() (string, error) { 81 if env := os.Getenv("NETRC"); env != "" { 82 return env, nil 83 } 84 dir, err := os.UserHomeDir() 85 if err != nil { 86 return "", err 87 } 88 base := ".netrc" 89 if runtime.GOOS == "windows" { 90 base = "_netrc" 91 } 92 return filepath.Join(dir, base), nil 93 } 94 95 func readNetrc() { 96 path, err := netrcPath() 97 if err != nil { 98 netrcErr = err 99 return 100 } 101 102 data, err := ioutil.ReadFile(path) 103 if err != nil { 104 if !os.IsNotExist(err) { 105 netrcErr = err 106 } 107 return 108 } 109 110 netrc = parseNetrc(string(data)) 111 }