-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
367 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package cmd | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
rootCmd.AddCommand(addCmd) | ||
} | ||
|
||
var addCmd = &cobra.Command{ | ||
Use: "add [IP] [HOSTNAME] [HOSTNAME] [HOSTNAME]...", | ||
Short: "Add hostnames to /etc/hosts", | ||
Long: `Add/Associate one or more hostnames to an IP address `, | ||
Args: func(cmd *cobra.Command, args []string) error { | ||
if len(args) < 2 { | ||
return errors.New("the \"add\" command requires an IP address and at least one hostname") | ||
} | ||
|
||
if validateIPAddress(args[0]) == false { | ||
return errors.New("the IP address provided is not a valid ipv4 or ipv6 address") | ||
} | ||
|
||
if ok, hn := validateHostnames(args[1:]); !ok { | ||
return errors.New(fmt.Sprintf("\"%s\" is not a valid hostname", hn)) | ||
} | ||
|
||
return nil | ||
}, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
if !Quiet { | ||
fmt.Printf("Adding host(s) \"%s\" to IP address %s\n", strings.Join(args[1:], " "), args[0]) | ||
} | ||
|
||
AddHosts(args[0], args[1:]) | ||
}, | ||
} | ||
|
||
func AddHosts(ip string, hosts []string) { | ||
|
||
etcHosts.AddHosts(ip, hosts) | ||
|
||
if DryRun { | ||
fmt.Print(etcHosts.RenderHostsFile()) | ||
return | ||
} | ||
|
||
err := etcHosts.Save() | ||
if err != nil { | ||
fmt.Printf("Error: could not save %s. Reason: %s\n", etcHosts.WriteFilePath, err.Error()) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
rootCmd.AddCommand(removeCmd) | ||
} | ||
|
||
var removeCmd = &cobra.Command{ | ||
Use: "remove [TYPE] [HOSTNAME|IP] [HOSTNAME|IP] [HOSTNAME|IP]...", | ||
Short: "Remove a hostname or ip address", | ||
Long: `Remove one or more hostnames or ip addresses from /etc/hosts`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
err := cmd.Help() | ||
if err != nil { | ||
fmt.Printf("Error: can not display help, reason: %s\n", err.Error()) | ||
os.Exit(1) | ||
} | ||
|
||
fmt.Println("Please specify a sub-command such as \"host\" or \"ip\"") | ||
os.Exit(1) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package cmd | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
removeCmd.AddCommand(removeHostCmd) | ||
} | ||
|
||
var removeHostCmd = &cobra.Command{ | ||
Use: "host [HOSTNAME] [HOSTNAME] [HOSTNAME]...", | ||
Short: "Remove hostnames from /etc/hosts", | ||
Long: `Remove one or more hostnames from /etc/hosts`, | ||
Args: func(cmd *cobra.Command, args []string) error { | ||
if len(args) < 1 { | ||
return errors.New("the \"remove hosts\" command requires at least one hostname to remove") | ||
} | ||
|
||
if ok, hn := validateHostnames(args); !ok { | ||
return errors.New(fmt.Sprintf("\"%s\" is not a valid hostname", hn)) | ||
} | ||
|
||
return nil | ||
}, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
if !Quiet { | ||
fmt.Printf("Removing host(s) \"%s\"\n", strings.Join(args, " ")) | ||
} | ||
|
||
RemoveHosts(args) | ||
}, | ||
} | ||
|
||
func RemoveHosts(hosts []string) { | ||
|
||
etcHosts.RemoveHosts(hosts) | ||
|
||
if DryRun { | ||
fmt.Print(etcHosts.RenderHostsFile()) | ||
return | ||
} | ||
|
||
err := etcHosts.Save() | ||
if err != nil { | ||
fmt.Printf("Error: could not save %s. Reason: %s\n", etcHosts.WriteFilePath, err.Error()) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package cmd | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
removeCmd.AddCommand(removeIpCmd) | ||
} | ||
|
||
var removeIpCmd = &cobra.Command{ | ||
Use: "ip [IP] [IP] [IP]...", | ||
Short: "Remove IP addresses from /etc/hosts", | ||
Long: `Remove one or more IP addresses from /etc/hosts`, | ||
Args: func(cmd *cobra.Command, args []string) error { | ||
if len(args) < 1 { | ||
return errors.New("the \"remove ip\" command requires at least one IP address to remove") | ||
} | ||
|
||
if ok, ip := validateIPAddresses(args); !ok { | ||
return errors.New(fmt.Sprintf("\"%s\" is not a valid ip address", ip)) | ||
} | ||
|
||
return nil | ||
}, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
if !Quiet { | ||
fmt.Printf("Removing ip(s) \"%s\"\n", strings.Join(args, " ")) | ||
} | ||
|
||
RemoveIPs(args) | ||
}, | ||
} | ||
|
||
func RemoveIPs(ips []string) { | ||
|
||
etcHosts.RemoveAddresses(ips) | ||
|
||
if DryRun { | ||
fmt.Print(etcHosts.RenderHostsFile()) | ||
return | ||
} | ||
|
||
err := etcHosts.Save() | ||
if err != nil { | ||
fmt.Printf("Error: could not save %s. Reason: %s\n", etcHosts.WriteFilePath, err.Error()) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"os" | ||
"regexp" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/txn2/txeh" | ||
) | ||
|
||
var rootCmd = &cobra.Command{ | ||
Use: "txeh", | ||
Short: "txeh is a /etc/hosts manager", | ||
Long: ` _ _ | ||
| |___ _____| |__ | ||
| __\ \/ / _ \ '_ \ | ||
| |_ > < __/ | | | | ||
\__/_/\_\___|_| |_| v` + VERSION + ` | ||
Add, remove and re-associate hostname entries in your /etc/hosts file. | ||
Read more including useage as a Go library at https://github.com/txn2/txeh`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
err := cmd.Help() | ||
if err != nil { | ||
fmt.Printf("Error: can not display help, reason: %s\n", err.Error()) | ||
os.Exit(1) | ||
} | ||
|
||
fmt.Println("Please specify a sub-command such as \"add\" or \"remove\"") | ||
os.Exit(1) | ||
}, | ||
PersistentPreRun: func(cmd *cobra.Command, args []string) { | ||
initEtcHosts() | ||
}, | ||
} | ||
|
||
var Quiet bool | ||
var HostsFileReadPath string | ||
var HostsFileWritePath string | ||
var DryRun bool | ||
|
||
var etcHosts *txeh.Hosts | ||
var hostnameRegex *regexp.Regexp | ||
|
||
func init() { | ||
rootCmd.PersistentFlags().BoolVarP(&DryRun, "dryrun", "d", false, "dry run, output to stdout (ignores quiet)") | ||
rootCmd.PersistentFlags().BoolVarP(&Quiet, "quiet", "q", false, "no output") | ||
rootCmd.PersistentFlags().StringVarP(&HostsFileReadPath, "read", "r", "", "(override) Path to read /etc/hosts file.") | ||
rootCmd.PersistentFlags().StringVarP(&HostsFileWritePath, "write", "w", "", "(override) Path to write /etc/hosts file.") | ||
|
||
// validate hostnames (allow underscore for service records) | ||
hostnameRegex = regexp.MustCompile(`^([A-Za-z]|[0-9]|-|_|\.)+$`) | ||
} | ||
|
||
func validateIPAddresses(ips []string) (bool, string) { | ||
for _, ip := range ips { | ||
if validateIPAddress(ip) == false { | ||
return false, ip | ||
} | ||
} | ||
|
||
return true, "" | ||
} | ||
|
||
func validateIPAddress(ip string) bool { | ||
|
||
if net.ParseIP(ip) == nil { | ||
return false | ||
} | ||
|
||
return true | ||
} | ||
|
||
func validateHostnames(hostnames []string) (bool, string) { | ||
for _, hn := range hostnames { | ||
if validateHostname(hn) != true { | ||
return false, hn | ||
} | ||
} | ||
|
||
return true, "" | ||
} | ||
|
||
func validateHostname(hostname string) bool { | ||
return hostnameRegex.MatchString(hostname) | ||
} | ||
|
||
func initEtcHosts() { | ||
if HostsFileReadPath == "" && HostsFileWritePath == "" { | ||
hosts, err := txeh.NewHostsDefault() | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
etcHosts = hosts | ||
return | ||
} | ||
|
||
hosts, err := txeh.NewHosts(&txeh.HostsConfig{ | ||
ReadFilePath: HostsFileReadPath, | ||
WriteFilePath: HostsFileWritePath, | ||
}) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
etcHosts = hosts | ||
} | ||
|
||
func Execute() { | ||
if err := rootCmd.Execute(); err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
const VERSION = "0.0.0" | ||
|
||
func init() { | ||
rootCmd.AddCommand(versionCmd) | ||
} | ||
|
||
var versionCmd = &cobra.Command{ | ||
Use: "version", | ||
Short: "Print the version number of txeh", | ||
Long: ``, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
fmt.Printf("txeh Version %s", VERSION) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "github.com/txn2/txeh/util/cmd" | ||
|
||
func main() { | ||
cmd.Execute() | ||
} |