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