-
Notifications
You must be signed in to change notification settings - Fork 0
/
hosts.go
147 lines (130 loc) · 3.26 KB
/
hosts.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package hosts
import (
"os"
"regexp"
"runtime"
"sort"
"strings"
"github.com/no-src/log"
)
func isWindows() bool {
return runtime.GOOS == "windows"
}
// PrintHosts print the hosts info
func PrintHosts(search ...string) {
hostsFile := "/etc/hosts"
if isWindows() {
sysRoot := os.Getenv("SYSTEMROOT")
hostsFile = sysRoot + `\System32\drivers\etc\hosts`
}
hostsBytes, err := os.ReadFile(hostsFile)
if err != nil {
log.Error(err, "read hosts file error")
return
}
var hosts HostItemList
hostsStr := string(hostsBytes)
// index 0 host row
// index 1 ip address
// index 2 host list
// index 3 last host matched
reg := regexp.MustCompile(`(\S+)(([\t ]+\S+)+)\r?\n?`)
hostMatches := reg.FindAllStringSubmatch(hostsStr, -1)
for _, match := range hostMatches {
if len(match) >= 4 {
ip := match[1]
hostnameStr := match[2]
if strings.Contains(ip, "#") == false {
hashIndex := strings.Index(hostnameStr, "#")
if hashIndex > 0 {
hostnameStr = hostnameStr[:hashIndex]
}
// index 0 hostname,contain whitespace
// index 1 hostname,not contain whitespace
hostnameReg := regexp.MustCompile(`[\t ]+(\S+)`)
hostNameMatches := hostnameReg.FindAllStringSubmatch(hostnameStr, -1)
var hostNameList []string
for _, hostNameMatch := range hostNameMatches {
hostNameList = append(hostNameList, hostNameMatch[1])
}
hosts = append(hosts, &HostItem{
IP: ip,
HostNameList: hostNameList,
})
}
}
}
log.Log("hosts[%s]", hostsFile)
log.Log("-------------------------------------------------")
hosts = recombine(hosts)
for _, item := range hosts {
var source []string
source = append(source, item.IP)
source = append(source, item.HostNameList...)
if find(source, search...) {
log.Log("%s %s", item.IP, strings.Join(item.HostNameList, " "))
}
}
}
func find(source []string, search ...string) bool {
if len(search) == 0 {
return true
}
for _, searchItem := range search {
for _, name := range source {
if strings.Contains(strings.ToLower(name), strings.ToLower(searchItem)) {
return true
}
}
}
return false
}
// recombine try to recombine hosts,group by ip and distinct,order by ip
func recombine(hosts HostItemList) (newHosts HostItemList) {
maps := make(map[string]*HostItem)
for _, hostItem := range hosts {
h := maps[hostItem.IP]
if h == nil {
h = &HostItem{
IP: hostItem.IP,
}
newHosts = append(newHosts, h)
maps[hostItem.IP] = h
}
h.HostNameList = append(h.HostNameList, hostItem.HostNameList...)
}
for _, hostItem := range newHosts {
hostItem.HostNameList = distinct(hostItem.HostNameList)
}
sort.Sort(sort.Reverse(newHosts))
return newHosts
}
func distinct(source []string) (target []string) {
if source == nil {
return nil
}
distinctMap := make(map[string]bool)
for _, item := range source {
exist := distinctMap[item]
if !exist {
target = append(target, item)
distinctMap[item] = true
}
}
sort.Strings(target)
return target
}
type HostItem struct {
IP string
HostNameList []string
}
type HostItemList []*HostItem
func (h HostItemList) Len() int {
return len(h)
}
func (h HostItemList) Less(i, j int) bool {
return strings.Compare(h[i].IP, h[j].IP) > 0
}
func (h HostItemList) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}