Compare commits

...

18 Commits

Author SHA1 Message Date
William Melody 8916c43efa Add `.github` configuration. 2023-06-27 16:59:08 -07:00
William Melody 9ea716f861
Use two-step homebrew install in README. 2020-10-06 23:13:23 -07:00
William Melody 9a929dc70f Update to version 3.6.4 2020-09-11 18:22:23 -07:00
William Melody 80699292a4 Use 'entries' terminology consistently. 2020-09-11 17:46:18 -07:00
William Melody 06ad3e8deb Add exit status to `list` and associated subcommands. 2020-09-11 17:40:47 -07:00
William Melody c74671613b Improve exit status documentation. 2020-09-11 17:22:02 -07:00
William Melody 0201480ffb Group helper variables and functions in Helpers section. 2020-09-11 17:01:29 -07:00
William Melody 0ce875c210 Use `sed -i` via a `_sed_i()` wrapper. 2020-09-11 17:01:29 -07:00
William Melody 6a58eb693d
Update README 2020-08-23 13:34:58 -07:00
William Melody 245188025a Improve `realpath` / `readlink` handling. 2020-08-16 10:14:48 -07:00
William Melody 39a182b47e Update Usage: ordering in `backups`. 2020-06-08 09:49:36 -07:00
William Melody bd7edba09b Improve spacing and comments in subcommands. 2020-06-08 09:42:58 -07:00
William Melody 5049abe817 Use alpha ordering for subcommand handling in `backup`. 2020-06-08 09:36:16 -07:00
William Melody 5c87ad62b0 Update version to 3.6.3 2020-06-07 18:07:12 -07:00
William Melody ca51f3f742 Remove extra newline. 2020-06-07 18:05:18 -07:00
William Melody ade1109cba Add missing `_warn` statements. 2020-06-07 17:22:20 -07:00
William Melody 3c383581c5 Update version to 3.6.2 2020-06-07 17:17:00 -07:00
William Melody 2346f6f814 Add missing `_download_from()` function. 2020-06-07 17:15:51 -07:00
14 changed files with 410 additions and 164 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: xwmx
custom: https://paypal.me/WilliamMelody

84
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,84 @@
###############################################################################
# .github/workflows/tests.yml
#
# NOTE: GitHub Actions does not allocate a TTY, preventing detection of
# piped input using `[[ -t 0 ]]`.
#
# More information:
#
# https://github.com/actions/runner/issues/241
#
# faketty is a GitHub action that uses work-arounds to provide a tty:
#
# https://github.com/marketplace/actions/faketty
#
# Scripts used by faketty for each platform:
#
# linux: `faketty`
#
# ```bash
# #!/bin/bash
#
# script -q -e -c "$*"
# ```
#
# win32: `faketty.ps1`
#
# ```posh
# Invoke-Expression "$args"
# ```
#
# darwin: `faketty`
#
# requires: `brew install expect`
#
# ```bash
# #!/bin/bash
#
# unbuffer $*
# ```
###############################################################################
name: "hosts · Test Suite"
on:
pull_request:
branches: [ master ]
push:
branches: [ master ]
workflow_dispatch:
jobs:
test-macos-11:
name: "Test: macOS Big Sur 11.0"
runs-on: macos-11.0
steps:
- uses: actions/checkout@v3
- name: "Setup"
run: |
brew update
brew install bats-core
brew install expect
- name: "Set $TERM=xterm"
run: printf "TERM=xterm\\n" >> $GITHUB_ENV
- name: "Run bats tests"
run: unbuffer bats test
test-ubuntu-latest:
name: "Test: Ubuntu Latest"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Setup"
run: |
sudo apt-get update
sudo apt-get install bats -y
- name: "Install bats-core"
run: |
git clone https://github.com/bats-core/bats-core.git "${HOME}/bats-core" &&
cd "${HOME}/bats-core"
git checkout 2e2e5df6adf0b846b411b6b2f7bb654cbc3e2c4e
sudo ./install.sh /usr/local
- name: "Set $TERM=xterm"
run: printf "TERM=xterm\\n" >> $GITHUB_ENV
- name: "Run bats tests"
run: script -q -e -c "bats test"

View File

@ -1,18 +0,0 @@
jobs:
include:
- os: linux
addons:
apt:
sources:
- sourceline: 'ppa:duggan/bats'
packages:
- bats
dist: bionic
language: minimal
- os: osx
before_install:
- brew install bats-core
osx_image: xcode11.3
script: bats test

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/xwmx/hosts.svg?branch=master)](https://travis-ci.org/xwmx/hosts)
[![Build Status](https://img.shields.io/github/actions/workflow/status/xwmx/hosts/tests.yml?branch=master)](https://github.com/xwmx/hosts/actions)
__ __
/ /_ ____ _____/ /______
@ -25,7 +25,8 @@ single, portable script that can be `curl`ed into any environment.
To install with [Homebrew](http://brew.sh/):
```bash
brew install xwmx/taps/hosts
brew tap xwmx/taps
brew install hosts
```
### npm
@ -159,7 +160,7 @@ address, domain, or regular expression:
```bash
> hosts remove example.com
Removing the following records:
Removing the following entries:
127.0.0.1 example.com
Are you sure you want to proceed? [y/N] y
Removed:
@ -191,7 +192,7 @@ Removed:
### Enabling / Disabling Entries
Add entries are enabled by default. Disabiling an entry comments it out
All entries are enabled by default. Disabiling an entry comments it out
so it has no effect, but remains in the hosts file ready to be enabled
again.
@ -329,7 +330,7 @@ alias hosts="hosts --auto-sudo"
Usage:
hosts [<search string>]
hosts add <ip> <hostname> [<comment>]
hosts backups [create | [compare | delete | restore | show] <filename>]
hosts backups [create | (compare | delete | restore | show) <filename>]
hosts block <hostname>...
hosts completions (check | install [-d | --download] | uninstall)
hosts disable (<ip> | <hostname> | <search string>)
@ -401,7 +402,7 @@ Usage:
Description:
List the existing IP / hostname pairs, optionally limited to a specified
state. When provided with a seach string, all matching enabled records will
state. When provided with a seach string, all matching enabled entries will
be printed.
Alias for `hosts list`
@ -417,7 +418,7 @@ Description:
Add a given IP address and hostname pair, along with an optional comment.
Exit status:
0 Success.
0 Entry successfully added.
1 Invalid parameters or entry exists.
```
@ -462,7 +463,7 @@ Description:
for IPv4 and both `fe80::1%lo0` and `::1` for IPv6.
Exit status:
0 Success.
0 <hostname> successfully blocked.
1 Invalid parameters or entry exists.
```
@ -483,6 +484,10 @@ Options:
Description:
Manage completion scripts. For more information, visit:
https://github.com/xwmx/hosts/blob/master/etc/README.md
Exit status:
0 Completions successfully installed.
1 Invalid parameters or other error.
```
### `hosts disable`
@ -492,11 +497,11 @@ Usage:
hosts disable (<ip> | <hostname> | <search string>)
Description:
Disable one or more records based on a given ip address, hostname, or
Disable one or more entries based on a given ip address, hostname, or
search string.
Exit status:
0 Success.
0 Entry successfully disabled.
1 Invalid parameters or entry not found.
```
@ -507,7 +512,11 @@ Usage:
hosts disabled
Description:
List all disabled records. This is an alias for `hosts list disabled`.
List all disabled entries. This is an alias for `hosts list disabled`.
Exit status:
0 One or more disabled entries found.
1 Invalid parameters or no disabled entries found.
```
### `hosts edit`
@ -527,11 +536,11 @@ Usage:
hosts enable (<ip> | <hostname> | <search string>)
Description:
Enable one or more disabled records based on a given ip address, hostname,
Enable one or more disabled entries based on a given ip address, hostname,
or search string.
Exit status:
0 Success.
0 Entry successfully enabled.
1 Invalid parameters or entry not found.
```
@ -542,7 +551,11 @@ Usage:
hosts enabled
Description:
List all enabled records. This is an alias for `hosts list enabled`.
List all enabled entries. This is an alias for `hosts list enabled`.
Exit status:
0 One or more enabled entries found.
1 Invalid parameters or no enabled entries found.
```
### `hosts file`
@ -573,8 +586,12 @@ Usage:
Description:
List the existing IP / hostname pairs, optionally limited to a specified
state. When provided with a seach string, all matching enabled records will
state. When provided with a seach string, all matching enabled entries will
be printed.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
```
### `hosts remove`
@ -588,12 +605,12 @@ Options:
--force Skip the confirmation prompt.
Description:
Remove one or more records based on a given IP address, hostname, or search
string. If an IP and hostname are both provided, only records matching the
Remove one or more entries based on a given IP address, hostname, or search
string. If an IP and hostname are both provided, only entries matching the
IP and hostname pair will be removed.
Exit status:
0 Success.
0 Entry successfully removed.
1 Invalid parameters or entry not found.
```
@ -605,6 +622,10 @@ Usage:
Description:
Search entries for <search string>.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
```
### `hosts show`
@ -617,7 +638,7 @@ Description:
Print entries matching a given IP address, hostname, or search string.
Exit status:
0 Success.
0 One or more matching entries found.
1 Invalid parameters or entry not found.
```
@ -644,7 +665,7 @@ Description:
Unblock one or more hostnames by removing the entries from the hosts file.
Exit status:
0 Success.
0 <hostname> successfully unblocked.
1 Invalid parameters or entry not found
```

286
hosts
View File

@ -52,7 +52,7 @@ IFS=$'\n\t'
# $_VERSION
#
# The most recent program version.
_VERSION="3.6.1"
_VERSION="3.6.4"
# $_ME
#
@ -71,33 +71,6 @@ HOSTS_DEFAULT_SUBCOMMAND="${HOSTS_DEFAULT_SUBCOMMAND:-list}"
# The path to the hosts file. This will almost always be /etc/hosts
HOSTS_PATH="${HOSTS_PATH:-/etc/hosts}"
# Space and tab for regular expressions
#
# sed regular expressions have slightly different behaviors dependending on
# the environment, and POSIX [[:space:]] matches whitespace characters other
# than just space and tab. These variables provide an easier, portable way to
# test for just these two characters.
export _TAB_=$'\t'
export _SPACE_=$' '
export _TAB_SPACE_="${_TAB_}${_SPACE_}"
export _TAB_SPACE_CC_="[${_TAB_SPACE_}]"
# $_SED_I_COMMAND
#
# `sed -i` takes an extension on macOS, but that extension can cause errors in
# GNU `sed`.
#
# NOTE: To use this command, call it with `"${_SED_I_COMMAND[@]}"`
#
# https://stackoverflow.com/q/43171648
# http://stackoverflow.com/a/16746032
if sed --help >/dev/null 2>&1
then # GNU
export _SED_I_COMMAND=(sed -i)
else # BSD
export _SED_I_COMMAND=(sed -i '')
fi
# $_REPO
#
# The <user>/<repo> identifier for the git repository.
@ -189,9 +162,20 @@ _warn() {
}
###############################################################################
# Utility Functions
# Helpers
###############################################################################
# Space and tab for regular expressions
#
# sed regular expressions have slightly different behaviors dependending on
# the environment, and POSIX [[:space:]] matches whitespace characters other
# than just space and tab. These variables provide an easier, portable way to
# test for just these two characters.
export _TAB_=$'\t'
export _SPACE_=$' '
export _TAB_SPACE_="${_TAB_}${_SPACE_}"
export _TAB_SPACE_CC_="[${_TAB_SPACE_}]"
# _contains()
#
# Usage:
@ -218,6 +202,54 @@ _contains() {
return 1
}
# _download_from()
#
# Usage:
# _download_from <url> [<outfile>]
#
# Description:
# Download the file at <url> and print to standard output or <outfile>.
# Uses `curl` if available, falling back to `wget`.
_download_from() {
local _downloaded=0
local _target_path="${2:-}"
local _url="${1:-}"
if [[ -z "${_url}" ]] ||
[[ ! "${_url}" =~ ^ftp|^http|^file|^mailto|^news|^telnet|^gopher ]]
then
return 1
fi
if [[ -n "${_target_path}" ]]
then
if hash "curl" 2>/dev/null
then
curl -s -L "${_url}" -o "${_target_path}" &&
_downloaded=1
elif hash "wget" 2>/dev/null
then
wget --quiet -O "${_target_path}" "${_url}" 2>/dev/null &&
_downloaded=1
fi
else
if hash "curl" 2>/dev/null
then
curl -s -L "${_url}" &&
_downloaded=1
elif hash "wget" 2>/dev/null
then
wget --quiet -O - "${_url}" 2>/dev/null &&
_downloaded=1
fi
fi
if ! ((_downloaded))
then
return 1
fi
}
# _join()
#
# Usage:
@ -300,8 +332,27 @@ _print_entries() {
done <<< "${_input}"
}
# _sed_i()
#
# `sed -i` takes an extension on macOS, but that extension can cause errors in
# GNU `sed`.
#
# https://stackoverflow.com/q/43171648
# https://stackoverflow.com/a/16746032
_sed_i() {
if sed --help >/dev/null 2>&1
then # GNU
sed -i "${@}"
else # BSD
sed -i '' "${@}"
fi
}
# _verify_write_permissions
#
# Usage:
# _verify_write_permissions
#
# Print a helpful error message when the specified operation can't be
# performed due to the lack of write permissions. If `$_AUTO_SUDO` is enabled,
# then run the command with sudo and exit with the command's exit value.
@ -422,7 +473,7 @@ A program for managing host file entries.
Usage:
${_ME} [<search string>]
${_ME} add <ip> <hostname> [<comment>]
${_ME} backups [create | [compare | delete | restore | show] <filename>]
${_ME} backups [create | (compare | delete | restore | show) <filename>]
${_ME} block <hostname>...
${_ME} completions (check | install [-d | --download] | uninstall)
${_ME} disable (<ip> | <hostname> | <search string>)
@ -492,7 +543,7 @@ Description:
Add a given IP address and hostname pair, along with an optional comment.
Exit status:
0 Success.
0 Entry successfully added.
1 Invalid parameters or entry exists.
HEREDOC
add() {
@ -599,7 +650,7 @@ backups() {
--skip-backup)
_skip_backup=1
;;
create|compare|delete|restore|show)
compare|create|delete|restore|show)
_subcommand="${__arg}"
;;
*)
@ -612,15 +663,6 @@ backups() {
done
case "${_subcommand}" in
create)
_verify_write_permissions
local _timestamp
_timestamp="$(date +"%Y%m%d%H%M%S")"
cp "${HOSTS_PATH}" "${HOSTS_PATH}--backup-${_timestamp}" && \
printf "Backed up to %s--backup-%s\\n" "${HOSTS_PATH}" "${_timestamp}"
;;
compare)
if [[ -z "${_filename:-}" ]]
then
@ -633,6 +675,15 @@ backups() {
diff -u "${HOSTS_PATH}" "${_hosts_dirname}/${_filename}"
;;
create)
_verify_write_permissions
local _timestamp
_timestamp="$(date +"%Y%m%d%H%M%S")"
cp "${HOSTS_PATH}" "${HOSTS_PATH}--backup-${_timestamp}" && \
printf "Backed up to %s--backup-%s\\n" "${HOSTS_PATH}" "${_timestamp}"
;;
delete)
if [[ -z "${_filename:-}" ]]
then
@ -723,7 +774,7 @@ Description:
for IPv4 and both \`fe80::1%lo0\` and \`::1\` for IPv6.
Exit status:
0 Success.
0 <hostname> successfully blocked.
1 Invalid parameters or entry exists.
HEREDOC
block() {
@ -756,6 +807,10 @@ Options:
Description:
Manage completion scripts. For more information, visit:
https://github.com/${_REPO}/blob/master/etc/README.md
Exit status:
0 Completions successfully installed.
1 Invalid parameters or other error.
HEREDOC
completions() {
local _BASH_COMP_NAME="hosts"
@ -779,7 +834,7 @@ completions() {
printf "Exists: %s\\n" "${_bash_completion_path}/${_BASH_COMP_NAME}"
fi
else
printf "Permission denied: %s\\n" "${_bash_completion_path}"
_warn printf "Permission denied: %s\\n" "${_bash_completion_path}"
fi
fi
@ -795,7 +850,7 @@ completions() {
printf "Exists: %s\\n" "${_zsh_completion_path}/${_ZSH_COMP_NAME}"
fi
else
printf "Permission denied: %s\\n" "${_zsh_completion_path}"
_warn printf "Permission denied: %s\\n" "${_zsh_completion_path}"
fi
fi
@ -851,8 +906,20 @@ completions() {
_download=1
fi
local _my_path="${0}"
if [[ -L "${_my_path}" ]]
then
if hash "realpath" 2>/dev/null
then
_my_path="$(realpath "${_my_path}")"
else
_my_path="$(readlink "${_my_path}")"
fi
fi
local _my_dir=
_my_dir="$(cd "$(dirname "$(realpath "$0")")"; pwd)"
_my_dir="$(cd "$(dirname "${_my_path}")"; pwd)"
if [[ -z "${_my_dir}" ]] || [[ ! -d "${_my_dir}" ]]
then
exit 1
@ -997,11 +1064,11 @@ Usage:
${_ME} disable (<ip> | <hostname> | <search string>)
Description:
Disable one or more records based on a given ip address, hostname, or
Disable one or more entries based on a given ip address, hostname, or
search string.
Exit status:
0 Success.
0 Entry successfully disabled.
1 Invalid parameters or entry not found.
HEREDOC
disable() {
@ -1016,6 +1083,11 @@ disable() {
else
_debug printf "disable() \${_search_string}: %s\\n" "${_search_string}"
# Regular Expression Notes
#
# - Note double periods in regular expression in order to emulate /.+/,
# which apparently doesn't work properly with all versions of sed.
local _regex_ip
_regex_ip="^\\(${_search_string}[${_TAB_SPACE_}]..*\\)$"
@ -1025,10 +1097,6 @@ disable() {
local _regex_hostname
_regex_hostname="^\\([^#]..*[${_TAB_SPACE_}]${_search_string}\\)$"
# Regular Expression Notes
#
# - Note double periods in regular expression in order to emulate /.+/,
# which apparently doesn't work properly with all versions of sed.
local _targets
_targets=$(
sed -n \
@ -1047,7 +1115,7 @@ disable() {
printf "Disabling:\\n%s\\n" "${_targets}"
"${_SED_I_COMMAND[@]}" \
_sed_i \
-e "s/${_regex_ip}/\\#disabled: \\1/g" \
-e "s/${_regex_commented_hostname}/\\#disabled: \\1/g" \
-e "s/${_regex_hostname}/\\#disabled: \\1/g" \
@ -1062,7 +1130,11 @@ Usage:
${_ME} disabled
Description:
List all disabled records. This is an alias for \`hosts list disabled\`.
List all disabled entries. This is an alias for \`hosts list disabled\`.
Exit status:
0 One or more disabled entries found.
1 Invalid parameters or no disabled entries found.
HEREDOC
disabled() {
list disabled
@ -1095,11 +1167,11 @@ Usage:
${_ME} enable (<ip> | <hostname> | <search string>)
Description:
Enable one or more disabled records based on a given ip address, hostname,
Enable one or more disabled entries based on a given ip address, hostname,
or search string.
Exit status:
0 Success.
0 Entry successfully enabled.
1 Invalid parameters or entry not found.
HEREDOC
enable() {
@ -1118,6 +1190,7 @@ enable() {
#
# - Note double periods in regular expression in order to emulate /.+/,
# which apparently doesn't work properly with all versions of sed.
local _regex_ip
_regex_ip="^\\#disabled: \\(${_search_string}[${_TAB_SPACE_}]..*\\)$"
@ -1145,7 +1218,7 @@ enable() {
printf "Enabling:\\n%s\\n" "${_targets}"
"${_SED_I_COMMAND[@]}" \
_sed_i \
-e "s/${_regex_ip}/\\1/g" \
-e "s/${_regex_commented_hostname}/\\1/g" \
-e "s/${_regex_hostname}/\\1/g" \
@ -1160,7 +1233,11 @@ Usage:
${_ME} enabled
Description:
List all enabled records. This is an alias for \`hosts list enabled\`.
List all enabled entries. This is an alias for \`hosts list enabled\`.
Exit status:
0 One or more enabled entries found.
1 Invalid parameters or no enabled entries found.
HEREDOC
enabled() {
list enabled
@ -1187,40 +1264,52 @@ Usage:
Description:
List the existing IP / hostname pairs, optionally limited to a specified
state. When provided with a seach string, all matching enabled records will
state. When provided with a seach string, all matching enabled entries will
be printed.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
HEREDOC
list() {
# Get the disabled records up front for the two cases where they are needed.
local _disabled_records
_disabled_records=$(
local _disabled_entries
_disabled_entries=$(
sed -n "s/^\\#disabled: \\(.*\\)$/\\1/p" "${HOSTS_PATH}"
)
# NOTE: use separate expressions since using `|` for the 'or' results in
# inconsistent behavior.
local _enabled_entries
_enabled_entries="$(
grep -v -e '^$' -e '^\s*\#' "${HOSTS_PATH}"
)"
if [[ -n "${1:-}" ]]
then
if [[ "${1}" == "disabled" ]]
then
_print_entries "${_disabled_records}"
[[ -z "${_disabled_entries}" ]] && return 1
_print_entries "${_disabled_entries}"
elif [[ "${1}" == "enabled" ]]
then
_print_entries "$(grep -v -e '^$' -e '^\s*\#' "${HOSTS_PATH}")"
[[ -z "${_enabled_entries}" ]] && return 1
_print_entries "${_enabled_entries}"
else
show "${1}"
fi
else
# NOTE: use separate expressions since using a | for the or results in
# inconsistent behavior.
local _enabled_records
_enabled_records="$(grep -v -e '^$' -e '^\s*\#' "${HOSTS_PATH}")"
_print_entries "${_enabled_records:-}"
[[ -z "${_enabled_entries}" ]] &&
[[ -z "${_enabled_entries}" ]] &&
return 1
if [[ -n "${_disabled_records:-}" ]]
_print_entries "${_enabled_entries:-}"
if [[ -n "${_disabled_entries:-}" ]]
then
[[ -n "${_enabled_records:-}" ]] && printf "\\n"
[[ -n "${_enabled_entries:-}" ]] && printf "\\n"
printf "Disabled:\\n"
printf "%s\\n" "---------"
_print_entries "${_disabled_records}"
_print_entries "${_disabled_entries}"
fi
fi
}
@ -1236,12 +1325,12 @@ Options:
--force Skip the confirmation prompt.
Description:
Remove one or more records based on a given IP address, hostname, or search
string. If an IP and hostname are both provided, only records matching the
Remove one or more entries based on a given IP address, hostname, or search
string. If an IP and hostname are both provided, only entries matching the
IP and hostname pair will be removed.
Exit status:
0 Success.
0 Entry successfully removed.
1 Invalid parameters or entry not found.
HEREDOC
remove() {
@ -1293,7 +1382,7 @@ remove() {
#
# Note double periods in regular expression in order to emulate /.+/,
# which apparently doesn't work properly with all versions of sed.
#
# IP / Hostname pair regular expressions:
local _regex_ip_hostname_commented
_regex_ip_hostname_commented="^\\(${_search_ip}[${_TAB_SPACE_}]*${_search_hostname}[${_TAB_SPACE_}]..*\\)$"
@ -1311,18 +1400,18 @@ remove() {
local _regex_hostname
_regex_hostname="^\\(..*[${_TAB_SPACE_}]${_search_string}\\)$"
local _target_records
local _target_entries
if ((_is_search_pair))
then
_target_records=$(
_target_entries=$(
sed -n \
-e "s/${_regex_ip_hostname_commented}/\\1/p" \
-e "s/${_regex_ip_hostname}/\\1/p" \
"${HOSTS_PATH}"
)
else
_target_records=$(
_target_entries=$(
sed -n \
-e "s/${_regex_ip}/\\1/p" \
-e "s/${_regex_commented_hostname}/\\1/p" \
@ -1331,14 +1420,14 @@ remove() {
)
fi
if [[ -z "${_target_records:-}" ]]
if [[ -z "${_target_entries:-}" ]]
then
_exit_1 printf "No matching records found.\\n"
_exit_1 printf "No matching entries found.\\n"
fi
if ! ((_force_skip_prompt))
then
printf "Removing the following records:\\n%s\\n" "${_target_records}"
printf "Removing the following entries:\\n%s\\n" "${_target_entries}"
while true
do
@ -1358,19 +1447,19 @@ remove() {
if ((_is_search_pair))
then
"${_SED_I_COMMAND[@]}" \
_sed_i \
-e "/${_regex_ip_hostname_commented}/d" \
-e "/${_regex_ip_hostname}/d" \
"${HOSTS_PATH}"
else
"${_SED_I_COMMAND[@]}" \
_sed_i \
-e "/${_regex_ip}/d" \
-e "/${_regex_commented_hostname}/d" \
-e "/${_regex_hostname}/d" \
"${HOSTS_PATH}"
fi
printf "Removed:\\n%s\\n" "${_target_records}"
printf "Removed:\\n%s\\n" "${_target_entries}"
}
desc "delete" "$(desc --get 'remove')"
delete() { remove "${@}"; }
@ -1383,6 +1472,10 @@ Usage:
Description:
Search entries for <search string>.
Exit status:
0 One or more matching entries found.
1 Invalid parameters or entry not found.
HEREDOC
search() {
if [[ -z "${1:-}" ]]
@ -1404,38 +1497,37 @@ Description:
Print entries matching a given IP address, hostname, or search string.
Exit status:
0 Success.
0 One or more matching entries found.
1 Invalid parameters or entry not found.
HEREDOC
show() {
if [[ -n "${1:-}" ]]
then
# Run `sed` before `grep` to avoid conflict that supresses `sed` output.
local _disabled_records
_disabled_records="$(
local _disabled_entries
_disabled_entries="$(
sed -n "s/^\\#disabled: \\(.*${1}.*\\)$/\\1/p" "${HOSTS_PATH}"
)"
local _enabled_records
_enabled_records="$(
local _enabled_entries
_enabled_entries="$(
grep --invert-match "^#" "${HOSTS_PATH}" | grep "${1}" || true
)"
if [[ -z "${_disabled_records}" ]] &&
[[ -z "${_enabled_records}" ]]
if [[ -z "${_disabled_entries}" ]] &&
[[ -z "${_enabled_entries}" ]]
then
_return_1 printf "No matching entries.\\n"
fi
_print_entries "${_enabled_records}"
_print_entries "${_enabled_entries}"
if [[ -n "${_disabled_records}" ]]
if [[ -n "${_disabled_entries}" ]]
then
[[ -n "${_enabled_records}" ]] && printf "\\n"
[[ -n "${_enabled_entries}" ]] && printf "\\n"
printf "Disabled:\\n"
printf "%s\\n" "---------"
_print_entries "${_disabled_records}"
_print_entries "${_disabled_entries}"
fi
else
help show
@ -1477,7 +1569,7 @@ Description:
Unblock one or more hostnames by removing the entries from the hosts file.
Exit status:
0 Success.
0 <hostname> successfully unblocked.
1 Invalid parameters or entry not found.
HEREDOC
unblock() {

2
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "hosts.sh",
"version": "3.6.1",
"version": "3.6.4",
"lockfileVersion": 1
}

View File

@ -1,6 +1,6 @@
{
"name": "hosts.sh",
"version": "3.6.1",
"version": "3.6.4",
"description": "A command line tool for managing hosts file entries.",
"global": true,
"install": "make install",

View File

@ -18,7 +18,7 @@ load test_helper
[[ ${status} -eq 0 ]]
}
@test "\`disabled\` with no arguments prints list of disabled records." {
@test "\`disabled\` with no arguments prints list of disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -34,6 +34,13 @@ load test_helper
[[ "${lines[2]}" == "" ]]
}
@test "\`disabled\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help disabled\` exits with status 0." {

View File

@ -18,7 +18,7 @@ load test_helper
[[ ${status} -eq 0 ]]
}
@test "\`enabled\` with no arguments prints list of enabled records." {
@test "\`enabled\` with no arguments prints list of enabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -36,6 +36,18 @@ load test_helper
[[ "${lines[4]}" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`enabled\` exits with status 1 when no matching entries found." {
{
run "${_HOSTS}" disable localhost
run "${_HOSTS}" disable broadcasthost
}
run "${_HOSTS}" enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help enabled\` exits with status 0." {

View File

@ -18,7 +18,7 @@ load test_helper
[[ ${status} -eq 0 ]]
}
@test "\`list\` prints lists of enabled and disabled records." {
@test "\`list\` prints lists of enabled and disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -60,7 +60,7 @@ Disabled:
[[ ${status} -eq 0 ]]
}
@test "\`list enabled\` prints list of enabled records." {
@test "\`list enabled\` prints list of enabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -78,6 +78,18 @@ Disabled:
[[ "${lines[4]}" =~ 127\.0\.0\.2[[:space:]]+example.com ]]
}
@test "\`list enabled\` exits with status 1 when no matching entries found." {
{
run "${_HOSTS}" disable localhost
run "${_HOSTS}" disable broadcasthost
}
run "${_HOSTS}" list enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts list disabled` #######################################################
@test "\`list disabled\` exits with status 0." {
@ -94,7 +106,7 @@ Disabled:
[[ ${status} -eq 0 ]]
}
@test "\`list disabled\` prints list of disabled records." {
@test "\`list disabled\` prints list of disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -110,6 +122,13 @@ Disabled:
[[ "${lines[2]}" == "" ]]
}
@test "\`list disabled\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" list disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts list <search string>` ################################################
@test "\`list <search string>\` exits with status 0." {
@ -125,7 +144,7 @@ Disabled:
[[ ${status} -eq 0 ]]
}
@test "\`list <search string>\` prints list of matching records." {
@test "\`list <search string>\` prints list of matching entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -140,7 +159,7 @@ Disabled:
[[ "${lines[2]}" == "" ]]
}
@test "\`list <search string>\` prints records with matching comments." {
@test "\`list <search string>\` prints entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
@ -155,7 +174,7 @@ Disabled:
}
@test "\`list <search string>\` prints disabled records with matching comments." {
@test "\`list <search string>\` prints disabled entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
@ -172,6 +191,13 @@ Disabled:
[[ "${lines[4]}" == "" ]]
}
@test "\`list <search string>\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" list query-that-matches-no-entries
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help list\` exits with status 0." {

View File

@ -53,7 +53,7 @@ load test_helper
run "${_HOSTS}" remove 127.0.0.3 --force
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${output} == "${_ERROR_PREFIX}No matching records found." ]]
[[ ${output} == "${_ERROR_PREFIX}No matching entries found." ]]
}
# `hosts remove <ip> --force` #################################################

View File

@ -29,14 +29,8 @@ load test_helper
run "${_HOSTS}" search
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
_expected="\
Usage:
hosts search <search string>
Description:
Search entries for <search string>."
_compare "'${_expected}'" "'${output}'"
[[ "${output}" == "${_expected}" ]]
[[ "${lines[0]}" == "Usage:" ]]
[[ "${lines[1]}" == " hosts search <search string>" ]]
}
# `hosts search enabled` ######################################################
@ -55,7 +49,7 @@ Description:
[[ ${status} -eq 0 ]]
}
@test "\`search enabled\` prints list of enabled records." {
@test "\`search enabled\` prints list of enabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -73,6 +67,18 @@ Description:
[[ "${lines[4]}" =~ 127.0.0.2[[:space:]]+example.com ]]
}
@test "\`search enabled\` exits with status 1 when no matching entries found." {
{
run "${_HOSTS}" disable localhost
run "${_HOSTS}" disable broadcasthost
}
run "${_HOSTS}" search enabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts search disabled` #####################################################
@test "\`search disabled\` exits with status 0." {
@ -89,7 +95,7 @@ Description:
[[ ${status} -eq 0 ]]
}
@test "\`search disabled\` prints list of disabled records." {
@test "\`search disabled\` prints list of disabled entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -105,6 +111,13 @@ Description:
[[ "${lines[2]}" == "" ]]
}
@test "\`search disabled\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" search disabled
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# `hosts search <search string>` ################################################
@test "\`search <search string>\` exits with status 0." {
@ -120,7 +133,7 @@ Description:
[[ ${status} -eq 0 ]]
}
@test "\`search <search string>\` prints list of matching records." {
@test "\`search <search string>\` prints list of matching entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -135,7 +148,7 @@ Description:
[[ "${lines[2]}" == "" ]]
}
@test "\`search <search string>\` prints records with matching comments." {
@test "\`search <search string>\` prints entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
@ -149,7 +162,7 @@ Description:
[[ "${lines[2]}" == "" ]]
}
@test "\`search <search string>\` prints disabled records with matching comments." {
@test "\`search <search string>\` prints disabled entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
@ -166,6 +179,13 @@ Description:
[[ "${lines[4]}" == "" ]]
}
@test "\`search <search string>\` exits with status 1 when no matching entries found." {
run "${_HOSTS}" search query-that-matches-no-entries
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${status} -eq 1 ]]
}
# help ########################################################################
@test "\`help search\` exits with status 0." {

View File

@ -21,7 +21,7 @@ load test_helper
# `hosts show <no matching>` ##################################################
@test "\`show <query>\` with no matching records with status 1." {
@test "\`show <query>\` with no matching entries with status 1." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -77,7 +77,7 @@ load test_helper
# `hosts show <search string>` ################################################
@test "\`show <search string>\` exits with status 0 and shows matching records." {
@test "\`show <search string>\` exits with status 0 and shows matching entries." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net
@ -94,7 +94,7 @@ load test_helper
[[ "${lines[2]}" == "" ]]
}
@test "\`show <search string>\` prints records with matching comments." {
@test "\`show <search string>\` prints entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"
@ -109,7 +109,7 @@ load test_helper
[[ "${lines[2]}" == "" ]]
}
@test "\`show <search string>\` prints disabled records with matching comments." {
@test "\`show <search string>\` prints disabled entries with matching comments." {
{
run "${_HOSTS}" add 0.0.0.0 example.com
run "${_HOSTS}" add 0.0.0.0 example.net "Example Comment"

View File

@ -49,7 +49,7 @@ load test_helper
run "${_HOSTS}" unblock example.net
printf "\${status}: %s\\n" "${status}"
printf "\${output}: '%s'\\n" "${output}"
[[ ${output} == "${_ERROR_PREFIX}No matching records found." ]]
[[ ${output} == "${_ERROR_PREFIX}No matching entries found." ]]
}
# `hosts unblock <hostname>` ##################################################