Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func add(c *cli.Context) error {
}

logrus.Debugln("flushing hosts file to disk")
if err := hf.Flush(); err != nil {
if err := flushHostsfile(c, hf); err != nil {
return cli.Exit(err.Error(), 2)
}

Expand Down
31 changes: 31 additions & 0 deletions cmd/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ var (
Aliases: []string{"q"},
Usage: "Turn on off all logging",
},
&cli.BoolFlag{
Name: "backup",
Aliases: []string{"b"},
Usage: "Create backup before modifying hosts file",
},
&cli.BoolFlag{
Name: "safe",
Usage: "Check for concurrent modifications before writing",
},
},
}
)
Expand Down Expand Up @@ -110,6 +119,28 @@ func loadHostsfile(c *cli.Context, readOnly bool) (*hostsfile.Hosts, error) {
return hf, nil
}

func flushHostsfile(c *cli.Context, hf *hostsfile.Hosts) error {
if c.Bool("safe") {
modified, err := hf.HasBeenModified()
if err != nil {
return err
}
if modified {
return fmt.Errorf("hosts file was modified by another process; reload and retry")
}
}

if c.Bool("backup") {
if err := hf.Backup(); err != nil {
logrus.Warnf("Failed to create backup: %v", err)
} else {
logrus.Debugf("Backup created at: %s", hf.BackupPath())
}
}

return hf.Flush()
}

func outputHostsfile(hf *hostsfile.Hosts, all bool) {
for _, line := range hf.Lines {
if !all {
Expand Down
82 changes: 72 additions & 10 deletions cmd/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,96 @@ func Check() *cli.Command {
return &cli.Command{
Name: "check",
Aliases: []string{"c"},
Usage: "Check if ip or host exists",
Usage: "Check if ip or host exists. With IP and hosts: check if all hosts are mapped to IP",
Action: check,
ArgsUsage: "[IP|HOST]",
ArgsUsage: "[IP|HOST] or [IP] [HOST] ([HOST]...)",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "quiet",
Aliases: []string{"q"},
Usage: "Suppress output, only return exit code",
},
&cli.BoolFlag{
Name: "any",
Usage: "With multiple hosts: succeed if ANY host matches (default: ALL must match)",
},
},
}
}

func check(c *cli.Context) error {
if c.Args().Len() < 1 {
logrus.Infof("No input, pass an ip address or hostname to check.")
return nil
}

hf, err := loadHostsfile(c, true)
hf, err := loadHostsfile(c, true) // readOnly=true, no sudo needed
if err != nil {
return err
}
input := c.Args().First()

if net.ParseIP(input) != nil {
if hf.HasIP(input) {
logrus.Infof("%s exists in hosts file\n", input)
args := c.Args().Slice()
firstArg := args[0]
quiet := c.Bool("quiet")

// Single argument: check if IP or hostname exists (backward compatible)
if c.Args().Len() == 1 {
if net.ParseIP(firstArg) != nil {
if hf.HasIP(firstArg) {
if !quiet {
logrus.Infof("%s exists in hosts file\n", firstArg)
}
return nil
}
}

if hf.HasHostname(firstArg) {
if !quiet {
logrus.Infof("%s exists in hosts file\n", firstArg)
}
return nil
}

return cli.Exit(fmt.Sprintf("%s does not match anything in the hosts file", firstArg), 1)
}

// Multiple arguments: first must be IP, rest are hostnames
if net.ParseIP(firstArg) == nil {
return cli.Exit(fmt.Sprintf("%s is not a valid IP address. When checking multiple hosts, first argument must be an IP.", firstArg), 2)
}

ip := firstArg
hosts := args[1:]

if c.Bool("any") {
// Check if ANY host is mapped to IP
if hf.HasAny(ip, hosts...) {
if !quiet {
logrus.Infof("At least one host is mapped to %s\n", ip)
}
return nil
}
return cli.Exit(fmt.Sprintf("None of the specified hosts are mapped to %s", ip), 1)
}

if hf.HasHostname(input) {
logrus.Infof("%s exists in hosts file\n", input)
// Default: Check if ALL hosts are mapped to IP
if hf.HasAll(ip, hosts...) {
if !quiet {
logrus.Infof("All specified hosts are mapped to %s\n", ip)
}
return nil
}

return cli.Exit(fmt.Sprintf("%s does not match anything in the hosts file", input), 1)
// Report which hosts are missing
if !quiet {
missing := []string{}
for _, host := range hosts {
if !hf.Has(ip, host) {
missing = append(missing, host)
}
}
return cli.Exit(fmt.Sprintf("Missing hosts for %s: %v", ip, missing), 1)
}

return cli.Exit("", 1)
}
2 changes: 1 addition & 1 deletion cmd/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func clean(c *cli.Context) error {
return debugFooter(c)
}

if err := h.Flush(); err != nil {
if err := flushHostsfile(c, h); err != nil {
return cli.Exit(err.Error(), 2)
}
return debugFooter(c)
Expand Down
2 changes: 1 addition & 1 deletion cmd/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func remove(c *cli.Context) error {
}

logrus.Debugln("flushing hosts file to disk")
if err := hf.Flush(); err != nil {
if err := flushHostsfile(c, hf); err != nil {
return cli.Exit(err.Error(), 2)
}

Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ module github.com/goodhosts/cli
go 1.21

require (
github.com/goodhosts/hostsfile v0.1.6
github.com/goodhosts/hostsfile v0.1.7
github.com/magefile/mage v1.15.0
github.com/olekukonko/tablewriter v0.0.5
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.8.4
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/urfave/cli/v2 v2.26.0
github.com/uwu-tools/magex v0.10.0
Expand Down
12 changes: 4 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/goodhosts/hostsfile v0.1.6 h1:aK6DxpNV6pZ1NbdvNE2vYBMTnvIJF5O2J/8ZOlp2eMY=
github.com/goodhosts/hostsfile v0.1.6/go.mod h1:bkCocEIf3Ca0hcBustUZoWYhOgKUaIK+47m8fBjoBx8=
github.com/goodhosts/hostsfile v0.1.7 h1:g8G2EU8t22AA7gNkXgC3kzj3aKvQBAf7azUonff1lNU=
github.com/goodhosts/hostsfile v0.1.7/go.mod h1:JsGCIqafGGoOkWYRPKowm/fH400CocwW+vIzFYEmZ2A=
github.com/icrowley/fake v0.0.0-20221112152111-d7b7e2276db2 h1:qU3v73XG4QAqCPHA4HOpfC1EfUvtLIDvQK4mNQ0LvgI=
github.com/icrowley/fake v0.0.0-20221112152111-d7b7e2276db2/go.mod h1:dQ6TM/OGAe+cMws81eTe4Btv1dKxfPZ2CX+YaAFAPN4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
Expand All @@ -31,14 +31,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
Expand Down
Loading