diff --git a/README.md b/README.md index 1fcd96e..3b0b5ec 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,127 @@ # Adsorber -[![Latest version](https://img.shields.io/badge/latest-v0.4.0-brightgreen.svg)](https://github.com/stablestud/adsorber/releases) +[![Latest version](https://img.shields.io/badge/latest-v0.5.0-brightgreen.svg)](https://github.com/stablestud/adsorber/releases) [![License](https://img.shields.io/github/license/stablestud/adsorber.svg)](https://github.com/stablestud/adsorber/blob/master/LICENSE) [![GitHub stars](https://img.shields.io/github/stars/stablestud/adsorber.svg)](https://github.com/stablestud/adsorber/stargazers) (Ad)sorber blocks ads by 'absorbing' and dumbing them into void. -Technically speaking, it adds ad-domains to the hosts file `/etc/hosts` with a redirection to a non-existent ip `0.0.0.0`. +Technically speaking, it adds ad-domains to the hosts file `/etc/hosts` with a redirection to a non-existent ip `0.0.0.0`. +You can consider it as [AdAway](https://github.com/AdAway/AdAway) for Linux machines. ## Features -* Block advertisements system-wide, not only in the browser. +* Blocks advertisements system-wide, not only in the browser. * Prevents annoying anti-adblockers from triggering. -* Update your blocked ad-domain list from external hosts-servers (like https://adaway.org/hosts.txt). -* Automatically update the hosts file per cronjob or systemd service. -* Revert to the previous hosts-file if the current hosts-file contains broken ad-servers +* Update your ad-domain list with domains from external external sources (like https://adaway.org/hosts.txt). +* Automatically update the hosts file with schedulers (cronjob or systemd service). +* Revert to the previous hosts file if the current hosts file contains broken ad-domains. * White- and blacklist. -Also it saves data, speeds up loading time and prevents some tracking of your browsing habits. For extensive privacy, I recommend using the script along browser add-ons like [NoScript](https://addons.mozilla.org/en-US/firefox/addon/noscript/) (for [Firefox 56 and below](https://noscript.net/getit)), [Privacy Badger](https://addons.mozilla.org/en-US/firefox/addon/privacy-badger17/) and [HTTPS Everywhere](https://addons.mozilla.org/en-US/firefox/addon/https-everywhere/). -Currently we are using the following hosts lists: -* [adaway.org](https://adaway.org/hosts.txt) -* [yoyo.org](https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext) -* & more to come. +## Requirements +* `root` rights (e.g. with `sudo`) +* The following should be supported on all distros by default: + * `/bin/sh` + * `/etc/hosts` + * `curl` or `wget` -To add your own hosts sources, just add them to the `sources.list` file. +## Installation +Download Adsorber from [`releases`](https://github.com/stablestud/adsorber/releases) or clone it. -## Usage +__Two possibilites:__ +* [Install](#Install-recommended) to system (recommended) +* [Portable mode](#Portable-mode) without installation + +### Install (recommended) +Adsorber will be placed onto your system (to `/usr/local/`). + +1. Execute the file `./place_files_onto_system.sh` +2. Run the command `adsorber setup` +3. Answer the prompts to configure Adsorber +4. Finished! + +If you have a super custom system you can configure where Adsorber should be placed, edit the relevant lines in `place_files_onto_system.sh` and `remove_files_from_system.sh` +However the default path (`/usr/local/`) is the default for external scripts on Linux (see [here](http://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLOCALLOCALHIERARCHY)) and should be fine for most systems. + +Placing Adsorber has the advantage to run it independently from the user who downloaded it, +preventing broken cronjobs/services as there is no risk that the files/directories of Adsorber will be accidentally deleted or moved. -### First steps .. installation to system -Adsorber can be installed into the system (recommended) for a more stable and robust usage. -This can be achieved through running `install_to_system.sh`, files will placed to `/usr/local/` if not other specified. -If you don't want Adsorber to be installed into your system run `portable_adsorber.sh`. +To reverse the steps (complete uninstall) run the script `./remove_files_from_system`. -Installing Adsorber into the system has the advantage that Adsorber can run independently from the user who downloaded it. -Also it prevents broken cronjobs/services as there is no risk that the files/directory of Adsorber will be accidentally deleted or moved. +### Portable mode +This mode will only download the recent ad-domains and merges them into your hosts file. +You won't be able to set a scheduler. + +1. Execute `./portable_adsorber.sh setup` to generate the config files +1. Execute `./portable_adsorber.sh setup` again to continue +2. Finished! + +If you want to update your hosts file you need to do it yourself by running `./portable_adsorber.sh update` + +Portable-mode won't touch the system except for `/etc/hosts` which is required to block ad-servers. A backup of it will be created at `/etc/hosts.original`. + +## Usage -To configure where it should be installed (to fit your system), edit the relevant lines in `install_to_system.sh` and `remove_from_system.sh`. For more help about the specific file run it with `--help`. +### `adsorber []` ### Default help screen of `adsorber help` ``` -Usage: adsorber [] +Usage: adsorber [|--help] -(Ad)sorber blocks ads by 'absorbing' and dumbing them into void. +(Ad)sorber blocks ads by "absorbing" and dumbing them into void. (with the help of the hosts file) -Operations: - install - setup necessary things needed for Adsorber +Operation (required): + setup - setup necessary things needed for Adsorber e.g., create backup file of hosts file, create scheduler which updates the host file once a week However this should've been done automatically. update - update hosts file with newest ad servers restore - restore hosts file to its original state - (it does not remove the schedule, this should be used temporary) - revert - reverts the hosts file to the last applied host file. - remove - completely remove changes made by Adsorber - e.g., remove scheduler (if set) + (it does not remove the scheduler, this should be used temporary) + revert - reverts the hosts file to the last applied (previous) host file. + disable - completely remove changes made by Adsorber + e.g., disable scheduler (if set) restore hosts file to its original state version - show version of this shell script help - show this help -Options: (optional) - -s, --systemd - use Systemd ... - -c, --cron - use Cronjob as scheduler (use with 'install') - -ns, --no-scheduler - skip scheduler creation (use with 'install') +Options (optional): -y, --yes, --assume-yes - answer all prompts with 'yes' -f, --force - force the update if no /etc/hosts backup has been created (dangerous) -h, --help - show specific help of specified operations + (e.g 'adsorber update --help) + --noformatting - turn off coloured and formatted output + +Scheduler options (use with 'setup'): + -ns, --no-scheduler - skip scheduler creation + -s, --systemd - setup Systemd as scheduler + -c, --cron - setup Cronjob ... + -H, --hourly - run scheduler once hourly + -D, --daily ... daily + -W, --weekly ... weekly + -M, --monthly ... monthly + -Q, --quarterly ... quarterly (4x a year) + -S, --semiannually ... semiannually (2x a year) + -Y, --yearly ... yearly + +Config files are located at: /usr/local/etc/adsorber/ Documentation: https://github.com/stablestud/adsorber If you encounter any issues please report them to the Github repository. ``` + ### Operations (required): +To run Adsorber one of the following operations must be given as first parameter. + Note: to get further information about a operation run `adsorber --help` -#### `adsorber install {options}`: +### adsorber `setup {options}`: You should run this command first. The command will: * backup your `/etc/hosts` file to `/etc/hosts.original` (if not other specified in `adsorber.conf`) -* install a scheduler which updates your hosts file with ad-server domains once a week. (either systemd, cronjob or none) -* install the newest ad-server domains in your hosts file. +* setup a scheduler which updates your hosts file with ad-server domains once a week. (either systemd, cronjob or none) +* fetch the newest ad-server domains in your hosts file. (same as `update`) Possible options are: * `-s, --systemd` @@ -86,8 +129,15 @@ Possible options are: * `-ns, --no-scheduler` * `-y, --yes, --assume-yes` * `-h, --help` - -#### `adsorber update {options}`: +* `-H, --hourly` +* `-D, --daily` +* `-W, --weekly` +* `-M, --monthly` +* `-Q, --quarterly` +* `-S, --semiannually` +* `-Y, --yearly` + +### adsorber `update {options}`: To keep the hosts file up-to-date. The command will: @@ -99,38 +149,38 @@ Possible options are: * `-f, --force` * `-h, --help` -#### `adsorber revert {options}`: +### adsorber `revert {options}`: To revert to the last applied hosts-file by Adsorber. - + The command will: * copy `/etc/hosts.previous` to `/etc/hosts`, overwriting the newest `/etc/hosts`. -This is useful if the new hosts file contains less ad-domains, because a server -was unreachable and you don't want to loose the ad-servers supplied from this server. +This is useful if the new hosts file contains less or no ad-domains, because a source +was unreachable and you don't want to loose the ad-servers supplied previously from this source. Possible option: * `-h, --help` -#### `adsorber restore {options}`: -To restore the hosts file temporary, without removing the backup. +### adsorber `restore {options}`: +To restore the hosts file to its original state, without removing the backup and scheduler. The command will: * copy `/etc/hosts.original` to `/etc/hosts`, overwriting the modified `/etc/hosts` by Adsorber. -Important: If you have a scheduler installed, it'll re-apply ad-server domains to your hosts file when triggered. -For this reason this command is used to temporary disable Adsorber, e.g. when it's blocking some sites you need access for a short period of time. -To re-apply run `adsorber update` +Important: If Adsorber's scheduler was set-up, it'll re-apply ad-server domains to your hosts file when triggered. +For this reason this command is used to temporary disable Adsorber, e.g. when it's blocking some sites you need to access for a short period of time. +To re-apply run `adsorber revert` (for previous host file) or `adsorber update` (for updated version). Possible option: * `-h, --help` -#### `adsorber remove {options}`: -To completely remove changes made by Adsorber. +### adsorber `disable {options}`: +Completely disable all background tasks (schedulers) and remove all changes made by Adsorber. The command will: -* remove all schedulers (systemd, cronjob) +* disable all schedulers (systemd, cronjob) * restore the hosts file to it's original state -* remove all leftovers (previous hosts-file, etc) +* remove all leftovers (previous hosts file, etc) Possible options are: * `-y, --yes, --assume-yes` @@ -139,36 +189,78 @@ Possible options are: ### Options (optional): #### `-s, --systemd`: -Use with `install`. -* Installs systemd scheduler, skipping the scheduler prompt. Files are placed into `/etc/systemd/system` by default. + +Option is only available with operation `setup`. +Adsorber uses Systemd as a scheduler to update your hosts file periodically. + +* Setup systemd scheduler, skipping the scheduler prompt. + +Files are placed into `/etc/systemd/system` by default. + #### `-c, --cronjob`: -Use with `install`. -* Installs the cron scheduler, skipping the scheduler prompt. File is placed into `/etc/cron.weekly/` by default. + +Option is only available with operation `setup`. +Adsorber uses Cronjob as a default scheduler to update your hosts file periodically. + +* Setup the cron scheduler, skipping the scheduler prompt. + +File is placed into `/etc/cron.weekly/` by default. + #### `-ns, --no-scheduler`: -Use with `install` -* Skips the installation of a scheduler. You'll need to update Adsorber manually with `adsorber update`. +Option is only available with operation `setup`. +Tells Adsorber no to install a scheduler. + +* Skips the setup of a scheduler, therefore skipping the scheduler prompt. + +You'll need to update Adsorber manually with `adsorber update`. + #### `-y, --yes, --assume-yes`: + Answers all prompts with `yes` e.g., -* `Do you really want to install Adsorber?` -* `Do you really want to remove Adsorber?` +* `Do you really want to setup Adsorber?` +* `Do you really want to disable Adsorber?` + +It'll not answer prompts which may harm your system. But `--force` will. -It'll not answer prompts which may harm your system. But `--force` will do it. #### `-f, --force`: -This will force the script to continue (dangerous) the update e.g., -* Continue if no backup has been created, overwriting the existing hosts file. + +Option is only available with operation `setup`. + +This will force the script to continue (dangerous) the update e.g., +* Continues if no backup has been created, overwriting the existing hosts file. + #### `-h, --help`: -If specified in conjunction with an operation, it'll show extended help about the operation. + +If specified with an operation, it'll show extended help about it. + +#### `--noformatting`: +Disables coloured and formatted output by Adsorber. +Useful for logging to files and output processing by other scripts. ## Settings: -To add or remove ad-domain sources edit the `soures.list` file which is created after the installation of Adsorber. -For a general configuration of Adsorber e.g., the path of the crontab installation, edit `adsorber.conf` -To add domains to the `whilelist` or `blacklist` edit the relevant files at the default config location. -The configuration's default location is at `/usr/local/etc/adsorber/` if installed to system. -If not, the config files should be placed at the scripts root directory. +By default the config files are located at `/usr/local/etc/adsorber/`. +In portable-mode the config files are being created at the scripts root directory after the first run. + +Config files you may want to edit: +* `adsorber.conf` - general configuration +* `sources.list` - sources to fetch from +* `whitelist` - domains which should not be blocked +* `blacklist` - domains which should be always blocked + +By default Adsorber uses the following external sources: +* [adaway.org](https://adaway.org/hosts.txt) (also used by AdAway) +* [yoyo.org](https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext) (also used by AdAway) + +To add your own ad-domain sources, just add them to the `sources.list` config file. + +## Logging: + +The schedulers (systemd service, cronjob) will pass their output to the Syslog process. +The syslog can be examined at `/var/log/syslog`. ## Todo for future releases -You're free to implement things listed/not listed in [`TODO.md`](https://github.com/stablestud/adsorber/blob/master/TODO.md) to Adsorber. +You're free to implement things listed/not listed in [`TODO.md`](https://github.com/stablestud/adsorber/blob/master/TODO.md) to Adsorber. Any additions are appreciated. :) ## License diff --git a/TODO.md b/TODO.md index c8d27cd..0e13251 100644 --- a/TODO.md +++ b/TODO.md @@ -1,15 +1,11 @@ ## Things considered for a future release/next release, ordered by priority ## Must: -* README.md update ## Should: -* interactive ability to set the update frequency -* save statistics to var/ and read from Adsorber ## Could: -* OpenRC support -* log-file +* save statistics to var/ and read from Adsorber * bash completion * proper unittest diff --git a/misc/README.md b/misc/README.md index c923721..12e5bbd 100644 --- a/misc/README.md +++ b/misc/README.md @@ -1 +1,7 @@ -This directory contains a few tools which may aid in the development of Adsorber. +### This directory contains a few tools which may aid in the development of Adsorber. + +#### clean.sh +Clean the script's root directory from junk (e.g whitelist, blacklist). + +#### shellcheck.sh +Checks all script files with the shellcheck application against common script issues. diff --git a/misc/clean.sh b/misc/clean.sh index 6dffb16..5e3ea59 100755 --- a/misc/clean.sh +++ b/misc/clean.sh @@ -1,4 +1,5 @@ #!/bin/sh +# Cleans the scripts root directory of config files created by portable_adsorber.sh readonly source_dir_path="$(cd "$(dirname "${0}")"/.. && pwd)" @@ -23,3 +24,5 @@ if [ -f "${source_dir_path}/sources.list" ]; then rm "${source_dir_path}/sources.list" -f echo "Removed sources.list" fi + +echo "Done." diff --git a/misc/shellcheck.sh b/misc/shellcheck.sh index 76f7aa9..902c1f6 100755 --- a/misc/shellcheck.sh +++ b/misc/shellcheck.sh @@ -8,19 +8,20 @@ readonly script_dir_path="$(cd "$(dirname "${0}")" && pwd)" if ! command -v shellcheck 2>/dev/null 1>&2; then echo "Shellcheck must be installed." + exit 1 fi echo "Running shellcheck ..." ( - cd -P -e "${script_dir_path}" || { echo "Couldn't descend to ${script_dir_path}"; exit 1; } + cd -P "${script_dir_path}" || { echo "Couldn't descend to ${script_dir_path}"; exit 1; } shellcheck -x \ + "${script_dir_path}/shellcheck.sh" \ "${script_dir_path}/../src/bin/adsorber" \ "${script_dir_path}/../portable_adsorber.sh" \ - "${script_dir_path}/../install_to_system.sh" \ - "${script_dir_path}/../remove_from_system.sh" \ - "${script_dir_path}/shellcheck.sh" + "${script_dir_path}/../place_files_onto_system.sh" \ + "${script_dir_path}/../remove_files_from_system.sh" echo "Done." ) diff --git a/install_to_system.sh b/place_files_onto_system.sh similarity index 63% rename from install_to_system.sh rename to place_files_onto_system.sh index 9ac0663..220718b 100755 --- a/install_to_system.sh +++ b/place_files_onto_system.sh @@ -44,14 +44,14 @@ printHelp() echo " Will place Adsorbers executables and other" echo " files relevant to Adsorber into the system." echo - printf "\\033[4;37mNote\\033[0m: Adsorbers own 'install' command will not do the same action as\\n" + printf "\\033[4;37mNote\\033[0m: Adsorbers own 'setup' command will not do the same action as\\n" echo "this script, as it will only setup the scheduler and backup the original hosts file." - echo "You may want to run 'adsorber install' afterwards" + echo "You may want to run 'adsorber setup' afterwards" echo echo "Usage: ${0} [option]:" echo echo "Options:" - echo " -y, --yes automatically reply the prompt with yes" + echo " -y, --yes automatically reply the confirmation prompt with yes" echo " -h, --help show this help screen" echo printLocation @@ -65,35 +65,31 @@ if [ "${prompt}" = "help" ] || [ "${prompt}" = "h" ] || [ "${prompt}" = "-h" ] | printHelp fi -echo "Current script location: ${script_dir_path}" -printLocation -echo +printf "Adsorber will be placed into /usr/local/*, which is the default path for external scripts.\\n\\n" if [ -z "${prompt}" ]; then - printf "Are you sure you want to install Adsorber into the system? [(Y)es/(N)o]: " + printf "Are you sure you want to place Adsorbers files onto the system? [(y)es/(N)o]: " read -r prompt fi case "${prompt}" in -[Yy] | --[Yy][Ee][Ss] | [Yy] | [Yy][Ee][Ss] ) - : - ;; + echo + ;; * ) - echo "Installation to the system has been cancelled." + echo "Placing files onto the system has been cancelled." exit 1 ;; esac # Check if user is root, if not exit. if [ "$(id -g)" -ne 0 ]; then - echo "You need to be root to install Adsorber into the system." 1>&2 + echo "You need to be root to place Adsorbers files onto the system." 1>&2 exit 126 fi -echo - ##[ Main exectuable ]########################################################### -echo "Placing main executable to ${executable_path}" +echo "Placing main executable (src/bin/adsorber) to ${executable_path}" mkdir -p "$(dirname ${executable_path})" @@ -103,50 +99,27 @@ sed "s|^readonly library_dir_path=\"\${executable_dir_path}/\\.\\./lib/\"$|reado | sed "s|^readonly config_dir_path=\"\${executable_dir_path}/\\.\\./\\.\\./\"$|readonly config_dir_path=\"${config_dir_path}\"|g" \ > "${executable_path}" -chmod u=rwx,g=rx,o=rx "${executable_path}" \ - || { - printf "Couldn't set permissions for %s" "${executable_path}" - } -chown root:root "${executable_path}" \ - || { - printf "Couldn't set ownership of %s" "${executable_path}" - } +chmod a+x "${executable_path}" ##[ Libraries ]################################################################# -echo "Placing other executables to ${library_dir_path}" +echo "Placing other executables (src/lib/) to ${library_dir_path}" mkdir -p "${library_dir_path}" cp -r "${script_dir_path}/src/lib/." "${library_dir_path}" -chmod -R u=rwx,g=rx,o=rx "${library_dir_path}" \ - || { - printf "Couldn't set permissions for %s" "${library_dir_path}" - } -chown -R root:root "${library_dir_path}" \ - || { - printf "Couldn't set ownership of %s" "${library_dir_path}" - } ##[ Shareables ]################################################################ -echo "Placing miscellaneous to ${shareable_dir_path}" +echo "Placing miscellaneous (src/share/) to ${shareable_dir_path}" mkdir -p "${shareable_dir_path}" cp -r "${script_dir_path}/src/share/." "${shareable_dir_path}" -chmod -R u=rwx,g=rx,o=rx "${shareable_dir_path}" \ - || { - printf "Couldn't set permissions for %s" "${shareable_dir_path}" - } -chown -R root:root "${shareable_dir_path}" \ - || { - printf "Couldn't set ownership of %s" "${shareable_dir_path}" - } ##[ Config files ]############################################################## -echo "Placing config files to ${config_dir_path}" +echo "Copying config files (src/share/default/) to ${config_dir_path}" mkdir -p "${config_dir_path}" @@ -155,27 +128,17 @@ cp "${script_dir_path}/src/share/default/default-blacklist" "${config_dir_path}/ cp "${script_dir_path}/src/share/default/default-whitelist" "${config_dir_path}/whitelist" cp "${script_dir_path}/src/share/default/default-sources.list" "${config_dir_path}/sources.list" -chmod -R u=rwx,g=rx,o=rx "${config_dir_path}" \ - || { - printf "Couldn't set permissions for %s" "${config_dir_path}" - } -chown -R root:root "${config_dir_path}" \ - || { - printf "Couldn't set ownership of %s" "${config_dir_path}" - } echo +echo "Adsorber files have been successfully placed onto the system." +printf "\\033[1;37mTo start going (to setup the scheduler and to backup the hosts file) run 'adsorber setup'\\033[0m\\n" ## We don't run Adsorber after installation yet -#adsorber install \ +#adsorber setup --noformatting \ # || { -# printf "\033[0;93mAdsorber was installed on your system, however something went wrong at\\n" +# printf "\\n\033[0;93mAdsorber has been placed onto your system, however something went wrong at\\n" # printf "running it.\\n" # printf "If a proxy server is in use, please change the config file\\n" # printf "(${config_dir_path}/adsorber.conf) to the appropriate proxy server.\\n\033[0m" -# echo "Run 'adsorber install' to try again." +# echo "Run 'adsorber setup' to try again." # } - -echo "Installation completed." -printf "\\033[1;37mTo start going and to setup the scheduler or to backup the hosts file run 'adsorber install'\\033[0m\\n" -echo "You can now delete this folder." diff --git a/portable_adsorber.sh b/portable_adsorber.sh index 42f844b..6aabbcb 100755 --- a/portable_adsorber.sh +++ b/portable_adsorber.sh @@ -16,7 +16,7 @@ runAdsorber() { echo "" # shellcheck disable=SC2086 - ( "${source_dir_path}/src/bin/adsorber" ${parameters} ) + ( "${source_dir_path}/src/bin/adsorber" "${parameters}" "--no-scheduler" ) exit_code="${?}" echo "" return "${exit_code}" @@ -25,10 +25,13 @@ runAdsorber() if runAdsorber; then echo "Adsorber in portable-mode exited with code ${exit_code}." else - # I defined exit code 80 as an error code if wrong or no input has been made + # I defined exit code 80 as an error code in the adsorber main executable + # if wrong or no input has been made if [ "${exit_code}" -eq 80 ]; then echo "You've supplied no or wrong parameters." fi echo "Adsorber in portable-mode exited with code ${exit_code}. Thats an error." + + exit ${exit_code} fi diff --git a/remove_from_system.sh b/remove_files_from_system.sh similarity index 69% rename from remove_from_system.sh rename to remove_files_from_system.sh index 87260c4..c95b6aa 100755 --- a/remove_from_system.sh +++ b/remove_files_from_system.sh @@ -6,15 +6,15 @@ # This file can run independently, no need to download the full repository to # remove an existing installation. -# Note: only run this file if Adsorber was installed into the system and not if -# it was used with portable-mode (portable_adsorber.sh) +# Note: only run this file if Adsorber was placed onto the system (via place_files_onto_system.sh) +# and not if it was used with portable-mode (portable_adsorber.sh) ##########[ Edit to fit your system ]########################################### # Define where the executable 'adsorber' is. readonly executable_path="/usr/local/bin/adsorber" -# Define where the other executable are. +# Define where the other executables are. readonly library_dir_path="/usr/local/lib/adsorber/" # Define the location of adsorbers shareable data (e.g. default config files...). @@ -23,17 +23,13 @@ readonly shareable_dir_path="/usr/local/share/adsorber/" # Define the location of the config files for adsorber. readonly config_dir_path="/usr/local/etc/adsorber/" -# Define the location of the log file. Not in use (yet). -#readonly log_file_path="/var/log/adsorber.log" - ## Following variables are only used when Adsorber's own removal activity failed -## and are used to remove Adsorber in the 'hard' way. Please change according to +## and are used to remove Adsorber manually. Please change according to ## your system configuration readonly hosts_file_path="/etc/hosts" readonly hosts_file_backup_path="/etc/hosts.original" readonly hosts_file_previous_path="/etc/hosts.previous" readonly systemd_dir_path="/etc/systemd/system" -readonly crontab_file_path="/etc/cron.weekly/80adsorber" readonly tmp_dir_path="/tmp/adsorber" ##########[ End of configuration ]############################################## @@ -43,7 +39,7 @@ readonly script_dir_path="$(cd "$(dirname "${0}")" && pwd)" printLocation() { - echo "Going to remove files from:" + echo "Going to remove files from:" echo " - main exectuable: ${executable_path}" echo " - other executables: ${library_dir_path}" echo " - configuration: ${config_dir_path}" @@ -81,13 +77,15 @@ if [ "${prompt}" = "help" ] || [ "${prompt}" = "h" ] || [ "${prompt}" = "-h" ] | printHelp fi -echo "Current script location: ${script_dir_path}" -printLocation -echo + +#echo "Current script location: ${script_dir_path}" +#printLocation +#echo + # Prompt user if sure about to remove Adsorber from the system if [ -z "${prompt}" ]; then - printf "Are you sure you want to remove Adsorber from the system? [(Y)es/(N)o]: " + printf "Are you sure you want to remove Adsorber from the system? [(y)es/(N)o]: " read -r prompt fi @@ -101,25 +99,68 @@ case "${prompt}" in ;; esac + # Check if user is root, if not exit. if [ "$(id -g)" -ne 0 ]; then echo "You need to be root to remove Adsorber from the system." 1>&2 exit 126 fi + # Run Adsorber's own removal, if it fails do it manually -printf "\\nRunning 'adsorber remove -y' ...\\n" -( adsorber remove -y ) \ - || { - echo - printf "\\033[0;93mSomething went wrong at running Adsorber's own removal action.\\nNo worries, I can handle it ...\\n\\033[0m" - echo "Maybe Adsorber has been already removed ?" - - # Doing it the hard way .., removing everything manually +if command -v adsorber 1>/dev/null; then + printf "\\nRunning 'adsorber disable -y --noformatting' ...\\n\\n" + ( adsorber "disable" "-y" "--noformatting" ) \ + || { + echo + printf "\\033[0;93mSomething went wrong at running Adsorber's own disable operation.\\nNo worries, I can handle it ...\\n\\033[0m" + echo "Maybe Adsorber has been already removed ?" + readonly _hard_way="true" + } +else + readonly _hard_way="true" +fi + + +# Doing it the hard way .., removing everything manually +if [ "${_hard_way}" = "true" ]; then + printf "\\nTrying portable_adsorber.sh ... " + + if "${script_dir_path}/portable_adsorber.sh" "disable" "-y" "--noformatting" 2>/dev/null 1>&2; then + printf "found\\n" + printf "Removed successfully Adsorber\\n" + else + printf "no luck\\n" + "${script_dir_path}/misc/clean.sh" 2>/dev/null 1>&2 + fi + + rm "${systemd_dir_path}/adsorber.timer" 2>/dev/null && echo "Removed ${systemd_dir_path}/adsorber.timer" rm "${systemd_dir_path}/adsorber.service" 2>/dev/null && echo "Removed ${systemd_dir_path}/adsorber.service" systemctl daemon-reload 2>/dev/null && echo "Reloaded systemctl daemon" - rm "${crontab_file_path}" 2>/dev/null && echo "Removed ${crontab_file_path}" + + # Remove all crontabs + if [ -f "/etc/cron.hourly/80adsorber" ]; then + rm "/etc/cron.hourly/80adsorber" 2>/dev/null \ + && echo "Removed cronjob from /etc/cron.hourly/" + fi + + if [ -f "/etc/cron.daily/80adsorber" ]; then + rm "/etc/cron.daily/80adsorber" 2>/dev/null \ + && echo "Removed cronjob from /etc/cron.daily/" + fi + + if [ -f "/etc/cron.weekly/80adsorber" ]; then + rm "/etc/cron.weekly/80adsorber" 2>/dev/null \ + && echo "Removed cronjob from /etc/cron.weekly/" + fi + + if [ -f "/etc/cron.monthly/80adsorber" ]; then + rm "/etc/cron.monthly/80adsorber" 2>/dev/null \ + && echo "Removed cronjob from /etc/cron.monthly/" + fi + + rm -r "${tmp_dir_path}" 2>/dev/null && echo "Removed ${tmp_dir_path}" if [ -f "${hosts_file_backup_path}" ]; then @@ -129,19 +170,22 @@ printf "\\nRunning 'adsorber remove -y' ...\\n" fi rm "${hosts_file_previous_path}" 2>/dev/null && echo "Removed ${hosts_file_previous_path}" - } +fi echo + # Remove placed files from the specified locations rm -r "${executable_path}" 2>/dev/null && echo "Removed ${executable_path}" rm -r "${library_dir_path}" 2>/dev/null && echo "Cleaned ${library_dir_path}" rm -r "${shareable_dir_path}" 2>/dev/null && echo "Cleaned ${shareable_dir_path}" rm -r "${config_dir_path}" 2>/dev/null && echo "Cleaned ${config_dir_path}" -# Remove the adsorber command from cache/hashtable + +# Remove the adsorber command from cache/hashtable. # Shells must be reloaded / reopened to have an effect echo "Clearing adsorber from shell cache ..." + if command -v hash 1>/dev/null; then # Works in bash hash -d adsorber 2>/dev/null @@ -153,6 +197,6 @@ else export PATH="${PATH}" fi -echo +echo echo "Done. Adsorber has been removed from the system." diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..79ed9f5 --- /dev/null +++ b/src/README.md @@ -0,0 +1,3 @@ +This directory/file hierachy shows how the files will be placed into `/usr/local/`. + +`/usr/local/` is the default path for external applications not managed by the distribution. diff --git a/src/bin/adsorber b/src/bin/adsorber index 0807eaf..24faa8f 100755 --- a/src/bin/adsorber +++ b/src/bin/adsorber @@ -6,7 +6,7 @@ # Variable naming: # under_score - used for global variables which are accessible between functions. -# _extra_under_score - used for local function variables. Should be unset afterwards. +# _extra_under_score - used for local function/file variables. Should be unset afterwards. # (Note the underscore in the beginning of _extra_under_score!) # shellcheck disable=SC2154 @@ -25,7 +25,7 @@ readonly shareable_dir_path="${executable_dir_path}/../share/" readonly config_dir_path="${executable_dir_path}/../../" -readonly version="0.4.0" +readonly version="0.5.0" readonly operation="${1}" if [ "${#}" -ne 0 ]; then @@ -42,20 +42,23 @@ checkRoot() exit 126 fi + checkPaths + sourceFiles + return 0 } checkForWrongParameters() { - if [ -n "${_wrong_operation}" ] || [ -n "${_wrong_option}" ]; then - showUsage - fi - if [ "${_option_help}" = "true" ]; then showSpecificHelp fi + if [ -n "${_wrong_operation}" ] || [ -n "${_wrong_option}" ]; then + showUsage + fi + return 0 } @@ -70,8 +73,8 @@ showUsage() echo "Adsorber: Invalid option: '${_wrong_option}'" 1>&2 fi - echo "Usage: adsorber []" - echo "Try '--help' for more information." + echo "Usage: adsorber [|--help]" + echo "Try 'help' for more information." exit 80 } @@ -79,34 +82,47 @@ showUsage() showHelp() { - echo "Usage: adsorber []" + echo "Usage: adsorber [|--help]" echo "" - echo "(Ad)sorber blocks ads by 'absorbing' and dumbing them into void." + echo "(Ad)sorber blocks ads by \"absorbing\" and dumbing them into void." echo " (with the help of the hosts file)" echo "" - echo "Operations (required):" - echo " install - setup necessary things needed for Adsorber" + echo "Operation (required):" + echo " setup - setup necessary things needed for Adsorber" echo " e.g., create backup file of hosts file," echo " create scheduler which updates the host file once a week" - echo " However this should've been done automatically." +# echo " However this should've been done automatically." echo " update - update hosts file with newest ad servers" echo " restore - restore hosts file to its original state" echo " (it does not remove the scheduler, this should be used temporary)" - echo " revert - reverts the hosts file to the last applied host file." - echo " remove - completely remove changes made by Adsorber" - echo " e.g., remove scheduler (if set)" + echo " revert - reverts the hosts file to the last applied (previous) host file." + echo " disable - completely remove changes made by Adsorber" + echo " e.g., disable scheduler (if set)" echo " restore hosts file to its original state" echo " version - show version of this shell script" echo " help - show this help" echo "" echo "Options (optional):" - echo " -s, --systemd - use Systemd ..." - echo " -c, --cron - use Cronjob as scheduler (use with 'install')" - echo " -ns, --no-scheduler - skip scheduler creation (use with 'install')" echo " -y, --yes, --assume-yes - answer all prompts with 'yes'" echo " -f, --force - force the update if no /etc/hosts backup" echo " has been created (dangerous)" echo " -h, --help - show specific help of specified operations" + echo " (e.g 'adsorber update --help)" + echo " --noformatting - turn off coloured and formatted output" + echo "" + echo "Scheduler options (use with 'setup'):" + echo " -ns, --no-scheduler - skip scheduler creation" + echo " -s, --systemd - setup Systemd as scheduler" + echo " -c, --cron - setup Cronjob ..." + echo " -H, --hourly - run scheduler once hourly" + echo " -D, --daily ... daily" + echo " -W, --weekly ... weekly" + echo " -M, --monthly ... monthly" + echo " -Q, --quarterly ... quarterly (4x a year)" + echo " -S, --semiannually ... semiannually (2x a year)" + echo " -Y, --yearly ... yearly" + echo + echo "Config files are located at: $(cd "${config_dir_path}" && pwd)/" echo echo "Documentation: https://github.com/stablestud/adsorber" echo "If you encounter any issues please report them to the Github repository." @@ -118,36 +134,41 @@ showHelp() showSpecificHelp() { case "${operation}" in - install ) - printf "\\033[4;37madsorber install []\\033[0m:\\n" + setup ) + printf "\\033[4;37madsorber setup []\\033[0m:\\n" echo echo "You should run this command first." - echo " (e.g. after installation to the system)" + echo " (e.g. after files have been placed onto the system)" echo echo "The command will:" echo " - backup your /etc/hosts file to /etc/hosts.original" echo " (if not other specified in adsorber.conf)" - echo " - install a scheduler which updates your hosts file with ad-domains" - echo " once a week. (either systemd, cronjob or none)" - echo " - install the newest ad-domains in your hosts file." - echo " (same as 'adsorber update')" - echo - echo "Note: this is not the same as the install_to_system.sh script." - echo "install_to_system.sh will place Adsorbers executable files into the system" - echo "so it can run directory independently, but it will not take the actions" - echo "described here. The same goes for 'remove'" + echo " - setup a scheduler which updates your hosts file with ad-domains periodically" + echo " (either systemd, cronjob or none)" + echo " - fetch the newest ad-domains to your hosts file." + echo " (it runs 'adsorber update')" echo echo "Possible options:" + echo " -y, --yes, --assume-yes - answer all prompts with 'yes'" echo " -s, --systemd - use Systemd ..." - echo " -c, --cronjob - use Cronjob as scheduler" + echo " -c, --cron - use Cronjob as scheduler" echo " -ns, --no-scheduler - skip scheduler creation" - echo " -y, --yes, --assume-yes - answer all prompts with 'yes'" echo " -h, --help - show this help screen" + echo " -H, --hourly - run scheduler once hourly" + echo " -D, --daily ... daily" + echo " -W, --weekly ... weekly" + echo " -M, --monthly ... monthly" + echo " -Q, --quarterly ... quarterly (4x a year)" + echo " -S, --semiannually ... semiannually (2x a year)" + echo " -Y, --yearly ... yearly" + echo " --noformatting - turn off coloured and formatted output" + echo + echo "Note: Cron supports only hourly, daily, weekly and monthly." ;; update ) printf "\\033[4;37madsorber update []\\033[0m:\\n" echo - echo "To keep the hosts file up-to-date." + echo "Updates your hosts files with the newest ad-domains fetched from the sources specified in 'sources.list'." echo echo "The command will:" echo " - fetch the newest ad-domains into your hosts file." @@ -156,53 +177,62 @@ showSpecificHelp() echo " -f, --force - force the update if no /etc/hosts backup" echo " has been created (dangerous)" echo " -h, --help - show this help screen" + echo " --noformatting - turn off coloured and formatted output" ;; restore ) printf "\\033[4;37madsorber restore []\\033[0m:\\n" echo - echo "To restore the hosts file temporary, without removing the backup." + echo "Restore the hosts file to its operating system default, without removing the backup or scheduler." echo echo "The command will:" echo " - copy /etc/hosts.original to /etc/hosts, overwriting the modified /etc/hosts by adsorber." echo - echo "Important: If you have a scheduler installed it'll re-apply ad-domains to your hosts" - echo "file when triggered." - echo "For this reason this command is used to temporary disable Adsorber." + echo "Note: If you have a scheduler set it'll re-apply ad-domains to your hosts file when triggered." + echo "For this reason this command should be used to temporary disable Adsorber." echo "(e.g. when it's blocking some sites you need access for a short period of time)" echo - echo "To re-apply run 'adsorber update'" + echo "To re-apply run 'adsorber revert' (for previous host file) or 'adsorber update' (for updated version)." echo - echo "Possible option:" + echo "Possible options:" echo " -h, --help - show this help screen" + echo " --noformatting - turn off coloured and formatted output" ;; revert ) printf "\\033[4;37madsorber revert []\\033[0m:\\n" echo - echo "To revert to the last applied hosts file." - echo "Good use if the current host file has been corruptea or misses some ad-domains." + echo "Revert the current hosts file to the previously applied hosts file." + echo "Use it if the current host file has been corrupted or misses previously applied ad-domains." echo echo "The command will:" echo " - copy /etc/hosts.previous to /etc/hosts, overwriting the current host file." echo - echo "To get the latest ad-domains run 'adsorber update'" + echo "To get the latest ad-domains run 'adsorber update'." echo - echo "Possible option:" + echo "Possible options:" echo " -h, --help - show this help screen" + echo " --noformatting - turn off coloured and formatted output" ;; - remove ) - printf "\\033[4;37madsorber remove []\\033[0m:\\n" + disable ) + printf "\\033[4;37madsorber disable []\\033[0m:\\n" echo - echo "To completely remove changes made by Adsorber." + echo "Completely disable all background tasks (schedulers) and remove all changes made by Adsorber." echo echo "The command will:" - echo " - remove all schedulers (systemd, cronjob)" + echo " - disable/remove all schedulers (systemd, cronjob)" echo " - restore the hosts file to it's original state" - echo " - remove all leftovers (e.g. /tmp/adsorber)" + echo " - remove all leftovers (e.g. /tmp/adsorber, previous hosts files, etc)" + echo + echo "It'll not remove/uninstall the 'adsorber' command from the system." + echo "To do this you need to run the 'remove_files_from_system.sh' script." echo echo "Possible options:" echo " -y, --yes, --assume-yes - answer all prompts with 'yes'" echo " -h, --help - show this help screen" + echo " --noformatting - turn off coloured and formatted output" ;; + * ) + showHelp + ;; esac exit 0 @@ -228,13 +258,23 @@ showVersion() duplicateOption() { if [ "${1}" = "scheduler" ]; then - echo "Adsorber: Duplicate option for scheduler: '${_option}'" 1>&2 + echo "Adsorber: Duplicate option for scheduler: '${2}'" 1>&2 echo "You may only select one:" - echo " -s, --systemd - use Systemd ..." - echo " -c, --cron - use Cronjob as scheduler (use with 'install')" - echo " -ns, --no-scheduler - skip scheduler creation (use with 'install')" - else - echo "Adsorber: Duplicate option: '${_option}'" 1>&2 + echo " -s, --systemd - use Systemd ..." + echo " -c, --cron - use Cronjob as scheduler" + echo " -ns, --no-scheduler - skip scheduler creation" + elif [ "${1}" = "frequency" ]; then + echo "Adsorber: Duplicate option for schedulers frequency: '${2}'" 1>&2 + echo "You may only select one:" + echo " -H, --hourly - run scheduler once hourly" + echo " -D, --daily ... daily" + echo " -W, --weekly ... weekly" + echo " -M, --monthly ... monthly" + echo " -Q, --quarterly ... quarterly (4x a year)" + echo " -S, --semiannually ... semiannually (2x a year)" + echo " -Y, --yearly ... yearly" + else + echo "Adsorber: Duplicate option: '${2}'" 1>&2 showUsage fi @@ -276,10 +316,14 @@ checkPaths() sourceFiles() { - # shellcheck source=../src/lib/install.sh - . "${library_dir_path}/install.sh" - # shellcheck source=../src/lib/remove.sh - . "${library_dir_path}/remove.sh" + # shellcheck source=../src/lib/colours.sh + . "${library_dir_path}/colours.sh" + # shellcheck source=../src/lib/cleanup.sh + . "${library_dir_path}/cleanup.sh" + # shellcheck source=../src/lib/setup.sh + . "${library_dir_path}/setup.sh" + # shellcheck source=../src/lib/disable.sh + . "${library_dir_path}/disable.sh" # shellcheck source=../src/lib/update.sh . "${library_dir_path}/update.sh" # shellcheck source=../src/lib/restore.sh @@ -288,8 +332,6 @@ sourceFiles() . "${library_dir_path}/revert.sh" # shellcheck source=../src/lib/config.sh . "${library_dir_path}/config.sh" - # shellcheck source=../src/lib/colours.sh - . "${library_dir_path}/colours.sh" # Maybe source them only when needed? # shellcheck source=../src/lib/cron/cron.sh @@ -300,34 +342,32 @@ sourceFiles() return 0 } -checkPaths -sourceFiles for _option in "${@}"; do case "${_option}" in - -[Ss] | --systemd ) + -s | --systemd ) if [ -z "${reply_to_scheduler_prompt}" ]; then readonly reply_to_scheduler_prompt="systemd" else - duplicateOption "scheduler" + duplicateOption "scheduler" "${_option}" fi ;; - -[Cc] | --cron ) + -[Cc] | --cron | --crontab | --cronjob ) if [ -z "${reply_to_scheduler_prompt}" ]; then readonly reply_to_scheduler_prompt="cronjob" else - duplicateOption "scheduler" + duplicateOption "scheduler" "${_option}" fi ;; -[Nn][Ss] | --no-scheduler ) if [ -z "${reply_to_scheduler_prompt}" ]; then readonly reply_to_scheduler_prompt="no-scheduler" else - duplicateOption "scheduler" + duplicateOption "scheduler" "${_option}" fi ;; - -[Yy] | --[Yy][Ee][Ss] | --assume-yes ) + -y | --[Yy][Ee][Ss] | --assume-yes ) if [ -z "${reply_to_prompt}" ]; then readonly reply_to_prompt="yes" else @@ -341,12 +381,65 @@ for _option in "${@}"; do duplicateOption fi ;; - "" ) - : # Do nothing - ;; - -[Hh] | --help | help ) + -H | --hourly ) + if [ -z "${frequency}" ]; then + readonly frequency="hourly" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -D | --daily ) + if [ -z "${frequency}" ]; then + readonly frequency="daily" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -W | --weekly ) + if [ -z "${frequency}" ]; then + readonly frequency="weekly" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -M | --monthly ) + if [ -z "${frequency}" ]; then + readonly frequency="monthly" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -Q | --quarterly ) + if [ -z "${frequency}" ]; then + readonly frequency="quarterly" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -S | --semi | --semiannually ) + if [ -z "${frequency}" ]; then + readonly frequency="semiannually" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -Y | --yearly | --annually ) + if [ -z "${frequency}" ]; then + readonly frequency="yearly" + else + duplicateOption "frequency" "${_option}" + fi + ;; + -h | --help | help ) _option_help="true" ;; + --noformatting ) + if [ -z "${use_formatting}" ]; then + readonly use_formatting="false" + else + echo "Can't turn off colour, variable'already set." 1>&2 + fi + ;; * ) _wrong_option="${_option}" 2>/dev/null ;; @@ -355,18 +448,18 @@ for _option in "${@}"; do done case "${operation}" in - install ) + setup ) checkForWrongParameters checkRoot config - install + setup update ;; - remove ) + disable ) checkForWrongParameters checkRoot config - remove + disable ;; update ) checkForWrongParameters @@ -401,6 +494,6 @@ case "${operation}" in ;; esac -printf "\\033[1;37mFinished successfully.\\033[0m\\n" +printf "%bFinished successfully.%b\\n" "${prefix_title}" "${prefix_reset}" exit 0 diff --git a/src/lib/cleanup.sh b/src/lib/cleanup.sh new file mode 100755 index 0000000..68739f0 --- /dev/null +++ b/src/lib/cleanup.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +# Author: stablestud +# Repository: https://github.com/stablestud/adsorber +# License: MIT, https://opensource.org/licenses/MIT + +# Variable naming: +# under_score - used for global variables which are accessible between functions. +# _extra_under_score - used for local function variables. Should be unset afterwards. +# (Note the underscore in the beginning of _extra_under_score!) + +# The following variables are declared globally. +# If you run this file independently following variables need to be set: +# ---variable:---------- ---default value:-- ---defined in:------------------- +# backedup Null (not set) src/lib/setup.sh +# hosts_file_backup_path /etc/hosts.original src/lib/config.sh, adsorber.conf +# setup_scheduler Null (not set) src/lib/systemd/systemd.sh, src/lib/cron/cron.sh +# prefix ' ' (two spaces) src/lib/colours.sh +# tmp_dir_path /tmp/adsorber src/bin/adsorber + +# The following functions are defined in different files. +# If you run this file independently following functions need to be emulated: +# ---function:- ---function defined in:--- +# systemdRemove src/lib/systemd/systemd.sh +# crontabRemove src/lib/cron/cron.sh + +# shellcheck disable=SC2154 + +# This function cleans-up all changed files if Adsorber runs into a problem +errorCleanUp() +{ + printf "%bCleaning up ...\\n" "${prefix_warning}" + + # Remove scheduler if it was setup (created) in the same run + case "${setup_scheduler}" in + cronjob ) + crontabRemove + ;; + systemd ) + systemdRemove + ;; + esac + + # Remove backup if backed-up in the same run + if [ "${backedup}" = "true" ]; then + echo "${prefix}Removed backup as the setup failed." + rm "${hosts_file_backup_path}" + fi + + # Remove /tmp/adsorber directory + if [ -d "${tmp_dir_path}" ]; then + rm -r "${tmp_dir_path}" + fi + + return 0 +} + + +# Normal clean-up function +cleanUp() +{ + echo "${prefix}Cleaning up ..." + + # Remove the /tmp/adsorber directory + rm -r "${tmp_dir_path}" + + return 0 +} diff --git a/src/lib/colours.sh b/src/lib/colours.sh index ea42cc3..bf49d25 100755 --- a/src/lib/colours.sh +++ b/src/lib/colours.sh @@ -9,81 +9,97 @@ # _extra_under_score - used for local function variables. Should be unset afterwards. # (Note the underscore in the beginning of _extra_under_score!) -readonly prefix=" " -readonly prefix_fatal="\\033[0;91mE " # 'E' in intensity red -readonly prefix_info="\\033[0;97m " # Intensity white -readonly prefix_input="> " -readonly prefix_title="\\033[1;37m" # Bold white -readonly prefix_warning="- " -readonly prefix_reset="\\033[0m" # Default colour -readonly prefix_underline="\\033[4;37m" # White Underline +# The following variables are declared globally. +# If you run this file independently following variables need to be set: +# ---variable:--- --default value:-- ----declared in:---- +# use_formatting true src/bin/adsorber, src/lib/cron/default-cronjob.sh, src/lib/systemd/default-service -# Regular Colors -#readonly BLACK='\033[0;30m' # Black -#readonly RED='\033[0;31m' # Red -#readonly GREEN='\033[0;32m' # Green -#readonly YELLOW='\033[0;33m' # Yellow -#readonly BLUE='\033[0;34m' # Blue -#readonly PURPLE='\033[0;35m' # Purple -#readonly CYAN='\033[0;36m' # Cyan -#readonly WHITE='\033[0;37m' # White +if [ "${use_formatting}" != "false" ]; then + readonly prefix=" " + readonly prefix_fatal="\\033[0;91mE " # 'E' in intensity red + readonly prefix_info="\\033[0;97m " # Intensity white + readonly prefix_input="> " + readonly prefix_title="\\033[1;37m" # Bold white + readonly prefix_warning="- " + readonly prefix_reset="\\033[0m" # Default colour + readonly prefix_underline="\\033[4;37m" # White Underline -# Bold -#readonly BBLACk='\033[1;30m' # Black -#readonly BRED='\033[1;31m' # Red -#readonly BGREEN='\033[1;32m' # Green -#readonly BYELLOW='\033[1;33m' # Yellow -#readonly BBLUE='\033[1;34m' # Blue -#readonly BPURPLE='\033[1;35m' # Purple -#readonly BCYAN='\033[1;36m' # Cyan -#readonly BWHITE='\033[1;37m' # White + # Regular Colors + #readonly BLACK='\033[0;30m' # Black + #readonly RED='\033[0;31m' # Red + #readonly GREEN='\033[0;32m' # Green + #readonly YELLOW='\033[0;33m' # Yellow + #readonly BLUE='\033[0;34m' # Blue + #readonly PURPLE='\033[0;35m' # Purple + #readonly CYAN='\033[0;36m' # Cyan + #readonly WHITE='\033[0;37m' # White -# Underline -#readonly UBLACK='\033[4;30m' # Black -#readonly URRED='\033[4;31m' # Red -#readonly UGREEn='\033[4;32m' # Green -#readonly UYELLOW='\033[4;33m' # Yellow -#readonly UBLUE='\033[4;34m' # Blue -#readonly UPURPLE='\033[4;35m' # Purple -#readonly UCYAN='\033[4;36m' # Cyan -#readonly uwhite='\033[4;37m' # White + # Bold + #readonly BBLACk='\033[1;30m' # Black + #readonly BRED='\033[1;31m' # Red + #readonly BGREEN='\033[1;32m' # Green + #readonly BYELLOW='\033[1;33m' # Yellow + #readonly BBLUE='\033[1;34m' # Blue + #readonly BPURPLE='\033[1;35m' # Purple + #readonly BCYAN='\033[1;36m' # Cyan + #readonly BWHITE='\033[1;37m' # White -# Background -#readonly BG_BLACK='\033[40m' # Black -#readonly BG_RED='\033[41m' # Red -#readonly BG_GREEN='\033[42m' # Green -#readonly BG_YELLOW='\033[43m' # Yellow -#readonly BG_BLUE='\033[44m' # Blue -#readonly BG_PURPLE='\033[45m' # Purple -#readonly BG_CYAN='\033[46m' # Cyan -#readonly BG_WHITE='\033[47m' # White + # Underline + #readonly UBLACK='\033[4;30m' # Black + #readonly URRED='\033[4;31m' # Red + #readonly UGREEn='\033[4;32m' # Green + #readonly UYELLOW='\033[4;33m' # Yellow + #readonly UBLUE='\033[4;34m' # Blue + #readonly UPURPLE='\033[4;35m' # Purple + #readonly UCYAN='\033[4;36m' # Cyan + #readonly uwhite='\033[4;37m' # White -# High Intensity -#readonly IBLACK='\033[0;90m' # Black -#readonly IRED='\033[0;91m' # Red -#readonly IGREEN='\033[0;92m' # Green -#readonly IYELLOW='\033[0;93m' # Yellow -#readonly IBLUE='\033[0;94m' # Blue -#readonly IPURPLE='\033[0;95m' # Purple -#readonly ICYAN='\033[0;96m' # Cyan -#readonly IWHITE='\033[0;97m' # White + # Background + #readonly BG_BLACK='\033[40m' # Black + #readonly BG_RED='\033[41m' # Red + #readonly BG_GREEN='\033[42m' # Green + #readonly BG_YELLOW='\033[43m' # Yellow + #readonly BG_BLUE='\033[44m' # Blue + #readonly BG_PURPLE='\033[45m' # Purple + #readonly BG_CYAN='\033[46m' # Cyan + #readonly BG_WHITE='\033[47m' # White -# Bold High Intensity -#readonly BIBLACK='\033[1;90m' # Black -#readonly BIRED='\033[1;91m' # Red -#readonly BIGREEN='\033[1;92m' # Green -#readonly BIYELLOW='\033[1;93m' # Yellow -#readonly BIBLUE='\033[1;94m' # Blue -#readonly BIPURPLE='\033[1;95m' # Purple -#readonly BICYAB='\033[1;96m' # Cyan -#readonly BIWHITE='\033[1;97m' # White + # High Intensity + #readonly IBLACK='\033[0;90m' # Black + #readonly IRED='\033[0;91m' # Red + #readonly IGREEN='\033[0;92m' # Green + #readonly IYELLOW='\033[0;93m' # Yellow + #readonly IBLUE='\033[0;94m' # Blue + #readonly IPURPLE='\033[0;95m' # Purple + #readonly ICYAN='\033[0;96m' # Cyan + #readonly IWHITE='\033[0;97m' # White -# High Intensity backgrounds -#readonly BG_IBLACK='\033[0;100m' # Black -#readonly BG_IRED='\033[0;101m' # Red -#readonly BG_IGREEN='\033[0;102m' # Green -#readonly BG_IYELLOW='\033[0;103m' # Yellow -#readonly BG_IBLUE='\033[0;104m' # Blue -#readonly BG_IPURPLE='\033[0;105m' # Purple -#readonly BG_ICYAN='\033[0;106m' # Cyan -#readonly BG_IWHITE='\033[0;107m' # White + # Bold High Intensity + #readonly BIBLACK='\033[1;90m' # Black + #readonly BIRED='\033[1;91m' # Red + #readonly BIGREEN='\033[1;92m' # Green + #readonly BIYELLOW='\033[1;93m' # Yellow + #readonly BIBLUE='\033[1;94m' # Blue + #readonly BIPURPLE='\033[1;95m' # Purple + #readonly BICYAB='\033[1;96m' # Cyan + #readonly BIWHITE='\033[1;97m' # White + + # High Intensity backgrounds + #readonly BG_IBLACK='\033[0;100m' # Black + #readonly BG_IRED='\033[0;101m' # Red + #readonly BG_IGREEN='\033[0;102m' # Green + #readonly BG_IYELLOW='\033[0;103m' # Yellow + #readonly BG_IBLUE='\033[0;104m' # Blue + #readonly BG_IPURPLE='\033[0;105m' # Purple + #readonly BG_ICYAN='\033[0;106m' # Cyan + #readonly BG_IWHITE='\033[0;107m' # White +else + unset prefix + unset prefix_fatal + unset prefix_info + unset prefix_input + unset prefix_title + unset prefix_warning + unset prefix_reset + unset prefix_underline +fi diff --git a/src/lib/config.sh b/src/lib/config.sh index 322a0b4..708d89b 100755 --- a/src/lib/config.sh +++ b/src/lib/config.sh @@ -11,23 +11,23 @@ # The following variables are declared globally. # If you run this file independently following variables need to be set: -# ---variable:-------- ---default value:------------ ----declared in:----- -# config_dir_path ${executable_dir_path}/../../ src/bin/adsorber -# debug false src/bin/adsorber -# options every parameter but first src/bin/adsorber -# operations the first parameter src/bin/adsorber -# prefix ' ' (two spaces) src/lib/colours.sh -# prefix_reset \033[0m src/lib/colours.sh -# prefix_title \033[1;37m src/lib/colours.sh -# prefix_warning '- ' src/lib/colours.sh -# shareable_dir_path ${executable_dir_path}/../share/ src/bin/adsorber -# tmp_dir_path /tmp/adsorber src/bin/adsorber -# version 0.2.2 or similar src/bin/adsorber +# ---variable:------ ---default value:--------------- ---declared in:------- +# config_dir_path ${executable_dir_path}/../../ src/bin/adsorber +# debug false src/bin/adsorber +# options every parameter but first src/bin/adsorber +# operations the first parameter src/bin/adsorber +# prefix ' ' (two spaces) src/lib/colours.sh +# prefix_reset \033[0m src/lib/colours.sh +# prefix_title \033[1;37m src/lib/colours.sh +# prefix_warning '- ' src/lib/colours.sh +# shareable_dir_path ${executable_dir_path}/../share/ src/bin/adsorber +# tmp_dir_path /tmp/adsorber src/bin/adsorber +# version 0.2.2 or similar src/bin/adsorber # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# remove_ErrorCleanUp src/lib/remove.sh +# --function:-- --function defined in:-- +# errorCleanUp src/lib/cleanup.sh # shellcheck disable=SC2154 @@ -52,16 +52,7 @@ config_CopySourceList() # Create sources.list if not found. Adsorber need sources.list to know from where to fetch hosts domains from if [ ! -f "${config_dir_path}/sources.list" ] || [ ! -s "${config_dir_path}/sources.list" ]; then cp "${shareable_dir_path}/default/default-sources.list" "${config_dir_path}/sources.list" \ - && echo "${prefix_warning}Created sources.list: to add new host sources edit this file." - - chown root:root -R "${config_dir_path}/sources.list" \ - || { - printf "%bCouldn't set ownership of %s\\n" "${prefix_warning}" "${config_dir_path}" - } - chmod u=rwx,g=rx,o=r -R "${config_dir_path}/sources.list" \ - || { - printf "%bCouldn't set permissions for %s\\n" "${prefix_warning}" "${config_dir_path}" - } + && echo "${prefix_warning}Created sources.list - to add new host sources edit this file." fi return 0 @@ -73,16 +64,7 @@ config_CopyWhiteList() # Create whitelist if not found, used to whitelist domains which should be excluded from blocking if [ ! -f "${config_dir_path}/whitelist" ] || [ ! -s "${config_dir_path}/whitelist" ]; then cp "${shareable_dir_path}/default/default-whitelist" "${config_dir_path}/whitelist" \ - && echo "${prefix_warning}Created whitelist: to allow specific domains edit this file." - - chown root:root -R "${config_dir_path}/whitelist" \ - || { - printf "%bCouldn't set ownership of %s\\n" "${prefix_warning}" "${config_dir_path}" - } - chmod u=rwx,g=rx,o=r -R "${config_dir_path}/whitelist" \ - || { - printf "%bCouldn't set permissions for %s\\n" "${prefix_warning}" "${config_dir_path}" - } + && echo "${prefix_warning}Created whitelist - to allow specific domains edit this file." fi return 0 @@ -94,16 +76,7 @@ config_CopyBlackList() # Create blacklist if not found, used to explicitly block domains if [ ! -f "${config_dir_path}/blacklist" ] || [ ! -s "${config_dir_path}/blacklist" ]; then cp "${shareable_dir_path}/default/default-blacklist" "${config_dir_path}/blacklist" \ - && echo "${prefix_warning}Created blacklist: to block additional domains edit this file." - - chown root:root -R "${config_dir_path}/blacklist" \ - || { - printf "%bCouldn't set ownership of %s\\n" "${prefix_warning}" "${config_dir_path}" - } - chmod u=rwx,g=rx,o=r -R "${config_dir_path}/blacklist" \ - || { - printf "%bCouldn't set permissions for %s\\n" "${prefix_warning}" "${config_dir_path}" - } + && echo "${prefix_warning}Created blacklist - to block additional domains edit this file." fi return 0 @@ -117,16 +90,9 @@ config_CopyConfig() printf "%bNo config file found. Creating default.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 echo "${prefix_warning}Please re-run the command to continue." - sed "s|@.*|# Config file for Adsorber v${version}|g" "${shareable_dir_path}/default/default-adsorber.conf" > "${config_dir_path}/adsorber.conf" + sed "s|@.*|# Config file for Adsorber v${version}|g" "${shareable_dir_path}/default/default-adsorber.conf" \ + > "${config_dir_path}/adsorber.conf" - chown root:root -R "${config_dir_path}/adsorber.conf" \ - || { - printf "%bCouldn't set ownership of %s\\n" "${prefix_warning}" "${config_dir_path}" - } - chmod u=rwx,g=rx,o=r -R "${config_dir_path}/adsorber.conf" \ - || { - printf "%bCouldn't set permissions for %s\\n" "${prefix_warning}" "${config_dir_path}" - } exit 126 fi @@ -140,7 +106,7 @@ config_FilterConfig() cp "${config_dir_path}/adsorber.conf" "${tmp_dir_path}/config" \ || { printf "%bCouldn't process config file.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - remove_ErrorCleanUp + errorCleanUp exit 126 } @@ -155,7 +121,6 @@ config_FilterConfig() sed -n "/^hosts_file_backup_path=/p" "${tmp_dir_path}/config" sed -n "/^hosts_file_previous_enable=/p" "${tmp_dir_path}/config" sed -n "/^hosts_file_previous_path=/p" "${tmp_dir_path}/config" - sed -n "/^crontab_dir_path=/p" "${tmp_dir_path}/config" sed -n "/^systemd_dir_path=/p" "${tmp_dir_path}/config" } > "${tmp_dir_path}/config-filtered" @@ -235,13 +200,6 @@ config_ReadConfig() echo "${prefix_warning}Duplicate configuration for 'hosts_file_previous_path', keeping the first value: ${hosts_file_previous_path}" fi ;; - crontab_dir_path=* ) - if [ -z "${crontab_dir_path}" ]; then - readonly "${_line}" - else - echo "${prefix_warning}Duplicate configuration for 'crontab_dir_path', keeping the first value: ${crontab_dir_path}" - fi - ;; systemd_dir_path=* ) if [ -z "${systemd_dir_path}" ]; then readonly "${_line}" @@ -253,9 +211,11 @@ config_ReadConfig() # This should never be reached, as the config # file was filtered by config_FilterConfig and # should not contain any unknown lines - printf "%bThis is scary: I extracted %s from the config file, however I shouldn't be able to.%b\\n" "${prefix_fatal}" "${_line}" "${prefix_reset}" + printf "%bThis is scary: I extracted %s from the config file, however I shouldn't be able to.%b\\n" \ + "${prefix_fatal}" "${_line}" "${prefix_reset}" + echo "Please report this error with your config file to https://github.com/stablestud/adsorber" - remove_ErrorCleanUp + errorCleanUp exit 1 ;; esac @@ -272,31 +232,42 @@ config_IsVariableSet() # These configurations are not mandatory needed by Adsorber, thus # if any of them were not defined, Adsorber will use the default value if [ -z "${primary_list}" ]; then - printf "%bprimary_list not set in adsorber.conf. Using default value: blacklist\\n" "${prefix_warning}" 1>&2 + printf "%bprimary_list not set in adsorber.conf. Using default value: blacklist\\n" \ + "${prefix_warning}" 1>&2 + readonly primary_list="blacklist" fi if [ -z "${use_partial_matching}" ]; then - printf "%buse_partial_matching not set in adsorber.conf. Using default value: true\\n" "${prefix_warning}" 1>&2 + printf "%buse_partial_matching not set in adsorber.conf. Using default value: true\\n" \ + "${prefix_warning}" 1>&2 + readonly use_partial_matching="true" fi if [ -z "${ignore_download_error}" ]; then - printf "%bignore_download_error not set in adsorber.conf. Using default value: false\\n" "${prefix_warning}" 1>&2 + printf "%bignore_download_error not set in adsorber.conf. Using default value: false\\n" \ + "${prefix_warning}" 1>&2 + readonly ignore_download_error="true" fi if [ -z "${hosts_file_previous_enable}" ]; then - printf "%bhosts_file_previous_enable not set in adsorber.conf. Using default value: true\\n" "${prefix_warning}" 1>&2 + printf "%bhosts_file_previous_enable not set in adsorber.conf. Using default value: true\\n" \ + "${prefix_warning}" 1>&2 + readonly hosts_file_previous_enable="true" fi # Check if essential configurations were set in the config file # if not abort, and call error clean-up function - if [ -z "${hosts_file_path}" ] || [ -z "${hosts_file_backup_path}" ] || [ -z "${crontab_dir_path}" ] || [ -z "${systemd_dir_path}" ] || [ -z "${hosts_file_previous_path}" ]; then + if [ -z "${hosts_file_path}" ] || [ -z "${hosts_file_backup_path}" ] \ + || [ -z "${systemd_dir_path}" ] || [ -z "${hosts_file_previous_path}" ]; then printf "%bMissing setting(s) in adsorber.conf.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - printf "%bPlease delete adsorber.conf in %s and run 'adsorber install' to create a new config file.\\n" "${prefix_warning}" "${config_dir_path}" 1>&2 - remove_ErrorCleanUp + printf "%bPlease delete adsorber.conf in %s and run 'adsorber setup' to create a new config file.\\n" \ + "${prefix_warning}" "${config_dir_path}" 1>&2 + + errorCleanUp exit 127 fi @@ -311,42 +282,58 @@ config_IsVariableValid() # and abort with the error clean-up function if [ "${primary_list}" != "blacklist" ] && [ "${primary_list}" != "whitelist" ]; then - printf "%bWrong 'primary_list' set in adsorber.conf. Choose either 'blacklist' or 'whitelist'%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + printf "%bWrong 'primary_list' set in adsorber.conf. Choose either 'blacklist' or 'whitelist'%b\\n" \ + "${prefix_fatal}" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ "${use_partial_matching}" != "true" ] && [ "${use_partial_matching}" != "false" ]; then - printf "%bWrong 'use_partial_matching' set in adsorber.conf. Possible option: 'true' or 'false'%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + printf "%bWrong 'use_partial_matching' set in adsorber.conf. Possible option: 'true' or 'false'%b\\n" \ + "${prefix_fatal}" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ "${ignore_download_error}" != "true" ] && [ "${ignore_download_error}" != "false" ]; then - printf "%bWrong 'ignore_download_error' set in adsorber.conf. Possible option: 'true' or 'false'%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + printf "%bWrong 'ignore_download_error' set in adsorber.conf. Possible option: 'true' or 'false'%b\\n" \ + "${prefix_fatal}" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ ! -f "${hosts_file_path}" ]; then - printf "%bWrong 'hosts_file_path' set in adsorber.conf. Can't access: %s%b\\n" "${prefix_fatal}" "${hosts_file_path}" "${prefix_reset}" 1>&2 + printf "%bWrong 'hosts_file_path' set in adsorber.conf. Can't access: %s%b\\n" \ + "${prefix_fatal}" "${hosts_file_path}" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ ! -d "$(dirname "${hosts_file_backup_path}")" ]; then - printf "%bWrong 'hosts_file_backup_path' set in adsorber.conf. Can't access: %s%b\\n" "${prefix_fatal}" "$(dirname "${hosts_file_backup_path}")" "${prefix_reset}" 1>&2 + printf "%bWrong 'hosts_file_backup_path' set in adsorber.conf. Can't access: %s%b\\n" \ + "${prefix_fatal}" "$(dirname "${hosts_file_backup_path}")" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ "${hosts_file_previous_enable}" != "true" ] && [ "${hosts_file_previous_enable}" != "false" ]; then - printf "%bWrong 'hosts_file_previous_enable' set in adsorber.conf. Possible options: 'true' or 'false'%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + printf "%bWrong 'hosts_file_previous_enable' set in adsorber.conf. Possible options: 'true' or 'false'%b\\n" \ + "${prefix_fatal}" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ ! -d "$(dirname "${hosts_file_previous_path}")" ]; then - printf "%bWrong 'hosts_file_previous_path' set in adsorber.conf. Can't access: %s%b\\n" "${prefix_fatal}" "$(dirname "${hosts_file_previous_path}")" "${prefix_reset}" 1>&2 + printf "%bWrong 'hosts_file_previous_path' set in adsorber.conf. Can't access: %s%b\\n" \ + "${prefix_fatal}" "$(dirname "${hosts_file_previous_path}")" "${prefix_reset}" 1>&2 + wrongVariable="true" fi if [ ! -d "$(dirname "${tmp_dir_path}")" ]; then - printf "%bWrong 'tmp_dir_path' set in adsorber.conf. Can't access: %s%b\\n" "${prefix_fatal}" "$(dirname "${tmp_dir_path}")" "${prefix_reset}" 1>&2 + printf "%bWrong 'tmp_dir_path' set in adsorber.conf. Can't access: %s%b\\n" \ + "${prefix_fatal}" "$(dirname "${tmp_dir_path}")" "${prefix_reset}" 1>&2 + wrongVariable="true" fi @@ -354,11 +341,9 @@ config_IsVariableValid() # If one or more values were invalid exit with error message if [ "${wrongVariable}" = "true" ]; then - remove_ErrorCleanUp + errorCleanUp exit 126 fi - - return 0 } @@ -375,22 +360,20 @@ config_PrintVariables() echo " - hosts_file_backup_path: ${hosts_file_backup_path}" echo " - hosts_file_previous_enable: ${hosts_file_previous_enable}" echo " - hosts_file_previous_path: ${hosts_file_previous_path}" - echo " - crontab_dir_path: ${crontab_dir_path}" echo " - systemd_dir_path: ${systemd_dir_path}" echo " - tmp_dir_path: ${tmp_dir_path}" echo " - executable_dir_path: ${executable_dir_path}" echo " - library_dir_path: ${library_dir_path}" echo " - shareable_dir_path: ${shareable_dir_path}" echo " - config_dir_path: ${config_dir_path}" - - return 0 + echo " - use_formatting: ${use_formatting}" } # Main function for calling config related tasks config() { - printf "%b" "${prefix_title}Reading configuration ... ${prefix_reset}\\n" + printf "%bReading configuration ...%b\\n" "${prefix_title}" "${prefix_reset}" config_CreateTmpDir config_CopySourceList config_CopyWhiteList @@ -404,6 +387,4 @@ config() if [ "${debug}" = "true" ]; then config_PrintVariables # used for debugging fi - - return 0 } diff --git a/src/lib/cron/cron.sh b/src/lib/cron/cron.sh index f696689..c8629cf 100755 --- a/src/lib/cron/cron.sh +++ b/src/lib/cron/cron.sh @@ -11,58 +11,123 @@ # The following variables are declared globally. # If you run this file independently following variables need to be set: -# ---variable:------- ---default value:-- ---declared in:--------- -# crontab_dir_path /etc/cron.weekly src/lib/config.sh, adsorber.conf +# ---variable:------- ---default value:------------ ---declared in:--------- # executable_dir_path the root dir of the script src/bin/adsorber +# frequency null (not set) src/bin/adsorber # library_dir_path ${executable_dir_path}/../lib src/bin/adsorber # prefix ' ' (two spaces) src/lib/colours.sh +# prefix_input ' ' (two spaces) src/lib/colours.sh # prefix_fatal '\033[0;91mE ' src/lib/colours.sh # prefix_reset \033[0m src/lib/colours.sh # prefix_warning '- ' src/lib/colours.sh # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# remove_ErrorCleanUp src/lib/remove.sh +# --function:-- ---function defined in:--- +# errorCleanUp src/lib/cleanup.sh # shellcheck disable=SC2154 -crontabInstall() +crontabSetup() { - echo "${prefix}Installing cronjob ..." + echo "${prefix}Setting up ${frequency_string} Cronjob ..." # Check if crontabs directory variable is correctly set, if not abort and call the error clean-up function if [ ! -d "${crontab_dir_path}" ]; then - printf "%bWrong crontab_dir_path set. Can't access: %s.%b\\n" "${prefix_fatal}" "${crontab_dir_path}" "${prefix_reset}" 1>&2 - echo "${prefix}Is a cron service installed? If not use systemd if possible." - remove_ErrorCleanUp + printf "%bWrong frequency set. Can't access: %s.%b\\n" \ + "${prefix_fatal}" "${crontab_dir_path}" "${prefix_reset}" 1>&2 + + echo "${prefix}Is a Cron service installed? If not use Systemd if possible." + errorCleanUp exit 126 fi - # Replace the @ place holder line with the location of adsorber + # Replace the @ place holder line with the location of adsorber in 80adsorber # and copy and manipulate the content to crontabs directory - sed "s|#@version@#|${version}|g" "${library_dir_path}/cron/80adsorber" \ - | sed "s|^#@\\/some\\/path\\/adsorber update@#$|${executable_dir_path}\\/adsorber update|g" \ + sed "s|#@version@#|${version}|g" "${library_dir_path}/cron/default-cronjob.sh" \ + | sed "s|#@\\/some\\/path\\/adsorber update@#|${executable_dir_path}\\/adsorber update --noformatting|g" \ + | sed "s/#@frequency@#/${frequency_string}/g" \ > "${crontab_dir_path}/80adsorber" chmod u=rwx,g=rx,o=rx "${crontab_dir_path}/80adsorber" chown root:root "${crontab_dir_path}/80adsorber" - # Make known that we have installed the crontab in this run, - # if we fail now, crontab will be also removed (see remove_ErrorCleanUp) - readonly installed_scheduler="cronjob" + # Make known that we have setup the Crontab in this run, + # if we fail now, Crontab will be also removed (see errorCleanUp) + readonly setup_scheduler="cronjob" +} + + +crontabPromptFrequency() +{ + if [ -z "${frequency}" ]; then + _used_input="true" + printf "%bHow often should the scheduler run? [(h)ourly/(d)aily/(W)eekly/(m)onthly]: " "${prefix_input}" + read -r frequency + fi + + case "${frequency}" in + [Hh] | [Hh][Oo][Uu][Rr] | [Hh][Oo][Uu][Rr][Ll][Yy] ) + readonly frequency_string="hourly" + readonly crontab_dir_path="/etc/cron.hourly/" + ;; + [Dd] | [Dd][Aa][Yy] | [Dd][Aa][Ii][Ll][Yy] ) + readonly frequency_string="daily" + readonly crontab_dir_path="/etc/cron.daily/" + ;; + [Ww] | "" | [Ww][Ee][Ee][Kk] | [Ww][Ee][Ee][Kk][Ll][Yy] ) + readonly frequency_string="weekly" + readonly crontab_dir_path="/etc/cron.weekly/" + ;; + [Mm] | [Mm][Oo][Nn][Tt][Hh] | [Mm][Oo][Nn][Tt][Hh][Ll][Yy] ) + readonly frequency_string="monthly" + readonly crontab_dir_path="/etc/cron.monthly/" + ;; + [Yy] | [Yy][Ee][Aa][Rr] | [Yy][Ee][Aa][Rr][Ll][Yy] | \ + [Aa] | [Aa][Nn][Nn][Uu][Aa][Ll] | [Aa][Nn][Nn][Uu][Aa][Ll][Ll][Yy] | \ + [Qq] | [Qq][Uu][Aa][Rr][Tt][Ee][Rr] | [Qq][Uu][Aa][Rr][Tt][Ee][Rr][Ll][Yy] | \ + [Ss] | [Ss][Ee][Mm][Ii] | [Ss][Ee][Mm][Ii][Aa][Nn][Nn][Uu][Aa][Ll][Ll][Yy] ) + if [ "${_used_input}" = "true" ]; then + echo "${prefix_warning}This frequency is only available with Systemd." 1>&2 + unset frequency + crontabPromptFrequency + else + printf "%bThis frequency is only available with Systemd.%b\\n" \ + "${prefix_fatal}" "${prefix_reset}" 1>&2 + errorCleanUp + exit 1 + fi + ;; + * ) + if [ "${_used_input}" = "true" ]; then + echo "${prefix_warning}Frequency '${frequency}' not understood." 1>&2 + unset frequency + crontabPromptFrequency + else + printf "%bFrequency '%s' not understood.%b\\n" \ + "${prefix_fatal}" "${frequency}" "${prefix_reset}" 1>&2 + errorCleanUp + exit 1 + fi + ;; + esac - return 0 + unset _used_input } crontabRemove() { - if [ -f "${crontab_dir_path}/80adsorber" ]; then - # Remove the crontab from /etc/cron.weekly - rm "${crontab_dir_path}/80adsorber" \ + if [ -f "/etc/cron.hourly/80adsorber" ] \ + || [ -f "/etc/cron.daily/80adsorber" ] \ + || [ -f "/etc/cron.weekly/80adsorber" ] \ + || [ -f "/etc/cron.monthly/80adsorber" ]; then + # Remove the crontab from /etc/cron.* or other if specified + rm /etc/cron.?????*/80adsorber \ || { - printf "%bCouldn't remove crontab %s\\n." "${prefix_warning}" "${crontab_dir_path}" 1>&2 + printf "%bCouldn't remove Crontab %s\\n." \ + "${prefix_warning}" "${crontab_dir_path}" 1>&2 + return 1 } @@ -70,6 +135,11 @@ crontabRemove() else echo "${prefix}Cronjob not installed. Skipping ..." fi +} - return 0 + +crontab() +{ + crontabPromptFrequency \ + && crontabSetup } diff --git a/src/lib/cron/80adsorber b/src/lib/cron/default-cronjob.sh similarity index 67% rename from src/lib/cron/80adsorber rename to src/lib/cron/default-cronjob.sh index 444693b..d41f5a6 100755 --- a/src/lib/cron/80adsorber +++ b/src/lib/cron/default-cronjob.sh @@ -1,13 +1,13 @@ #!/bin/sh # # (Ad)sorber v#@version@# crontab file -# Updates the hosts file once a week. +# Updates the hosts file #@frequency@#. # # For more information: https://github.com/stablestud/adsorber # Or send me an email: # -# adsorber install --cron: +# adsorber setup --cron: # By default this file is going to be copied into /etc/cron.weekly/ if not # other specified. -#@/some/path/adsorber update@# +#@/some/path/adsorber update@# 2>&1 | logger -i -e -t Adsorber diff --git a/src/lib/disable.sh b/src/lib/disable.sh new file mode 100755 index 0000000..fc2fb43 --- /dev/null +++ b/src/lib/disable.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +# Author: stablestud +# Repository: https://github.com/stablestud/adsorber +# License: MIT, https://opensource.org/licenses/MIT + +# Variable naming: +# under_score - used for global variables which are accessible between functions. +# _extra_under_score - used for local function variables. Should be unset afterwards. +# (Note the underscore in the beginning of _extra_under_score!) + +# The following variables are declared globally. +# If you run this file independently following variables need to be set: +# ---variable:---------- ---default value:-- ---defined in:------------------- +# hosts_file_path /etc/hosts src/lib/config.sh, adsorber.conf +# hosts_file_backup_path /etc/hosts.original src/lib/config.sh, adsorber.conf +# prefix ' ' (two spaces) src/lib/colours.sh +# prefix_fatal '\033[0;91mE ' src/lib/colours.sh +# prefix_input ' ' (two spaces) src/lib/colours.sh +# prefix_reset \033[0m src/lib/colours.sh +# prefix_title \033[1;37m src/lib/colours.sh +# prefix_warning '- ' src/lib/colours.sh +# reply_to_prompt Null (not set) src/bin/adsorber + +# The following functions are defined in different files. +# If you run this file independently following functions need to be emulated: +# --function:-- ---function defined in:--- +# cleanUp src/lib/cleanup.sh +# errorCleanUp src/lib/cleanup.sh +# systemdRemove src/lib/systemd/systemd.sh +# crontabRemove src/lib/cron/cron.sh + +# shellcheck disable=SC2154 + +disable_Prompt() +{ + # Ask if the user is sure about to remove Adsorber + if [ -z "${reply_to_prompt}" ]; then + printf "%bDo you really want to disable Adsorber? [y/N] %b" "${prefix_input}" "${prefix_reset}" + read -r reply_to_prompt + fi + + case "${reply_to_prompt}" in + [Yy] | [Yy][Ee][Ss] ) + : # Do nothing + ;; + * ) + # If other input then Yes, abort and call error clean-up function + printf "%bDisable cancelled.\\n" "${prefix_warning}" 1>&2 + errorCleanUp + exit 130 + ;; + esac + + return 0 +} + + +disable_HostsFile() +{ + # Moves the original hosts file (backed-up at /etc/hosts.original) + # to /etc/hosts, replacing the current one + if [ -f "${hosts_file_backup_path}" ]; then + mv "${hosts_file_backup_path}" "${hosts_file_path}" \ + && echo "${prefix}Successfully restored ${hosts_file_path}" + else + # If /etc/hosts.original was not found, abort and call the error clean-up function + printf "%bCan not restore hosts file. Original hosts file does not exist.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + echo "${prefix}Maybe you've already disabled Adsorber?" 1>&2 + errorCleanUp + exit 1 + fi + + return 0 +} + + +disable_PreviousHostsFile() +{ + # If found, remove /etc/hosts.previous + if [ -f "${hosts_file_previous_path}" ]; then + rm "${hosts_file_previous_path}" \ + && echo "${prefix}Removed previous hosts file." + else + echo "${prefix}Previous hosts file does not exist. Ignoring ..." + fi + + return 0 +} + + +# Main function of disable.sh +disable() +{ + printf "%bDisabling Adsorber ...%b\\n" "${prefix_title}" "${prefix_reset}" + disable_Prompt + systemdRemove + crontabRemove + disable_HostsFile + disable_PreviousHostsFile + cleanUp + + return 0 +} diff --git a/src/lib/remove.sh b/src/lib/remove.sh deleted file mode 100755 index f367b87..0000000 --- a/src/lib/remove.sh +++ /dev/null @@ -1,147 +0,0 @@ -#!/bin/sh - -# Author: stablestud -# Repository: https://github.com/stablestud/adsorber -# License: MIT, https://opensource.org/licenses/MIT - -# Variable naming: -# under_score - used for global variables which are accessible between functions. -# _extra_under_score - used for local function variables. Should be unset afterwards. -# (Note the underscore in the beginning of _extra_under_score!) - -# The following variables are declared globally. -# If you run this file independently following variables need to be set: -# ---variable:------- ---default value:--- ---defined in:------------------ -# backedup Null (not set) src/lib/install.sh -# hosts_file_path /etc/hosts src/lib/config.sh, adsorber.conf -# hosts_file_backup_path /etc/hosts.original src/lib/config.sh, adsorber.conf -# installed_scheduler Null (not set) src/lib/systemd/systemd.sh, src/lib/cron/cron.sh -# prefix ' ' (two spaces) src/lib/colours.sh -# prefix_fatal '\033[0;91mE ' src/lib/colours.sh -# prefix_input ' ' (two spaces) src/lib/colours.sh -# prefix_reset \033[0m src/lib/colours.sh -# prefix_title \033[1;37m src/lib/colours.sh -# prefix_warning '- ' src/lib/colours.sh -# reply_to_prompt Null (not set) src/bin/adsorber -# tmp_dir_path /tmp/adsorber src/bin/adsorber - -# The following functions are defined in different files. -# If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# systemdRemove src/lib/systemd/systemd.sh -# crontabRemove src/lib/cron/cron.sh - -# shellcheck disable=SC2154 - -# This function cleans-up all changed files if Adsorber runs into a problem -remove_ErrorCleanUp() -{ - printf "%bCleaning up ...\\n" "${prefix_warning}" - - # Remove scheduler if it was installed in the same run - case "${installed_scheduler}" in - cronjob ) - crontabRemove - ;; - systemd ) - systemdRemove - ;; - esac - - # Remove backup if backed-up in the same run - if [ "${backedup}" = "true" ]; then - echo "${prefix}Removed backup as the installation failed." - rm "${hosts_file_backup_path}" - fi - - # Remove /tmp/adsorber directory - if [ -d "${tmp_dir_path}" ]; then - rm -r "${tmp_dir_path}" - fi - - return 0 -} - - -# Normal clean-up function -remove_CleanUp() -{ - echo "${prefix}Cleaning up ..." - - # Remove the /tmp/adsorber directory - rm -r "${tmp_dir_path}" - - return 0 -} - - -remove_Prompt() -{ - # Ask if the user is sure about to remove Adsorber - if [ -z "${reply_to_prompt}" ]; then - printf "%bDo you really want to remove Adsorber? [Y/n] %b" "${prefix_input}" "${prefix_reset}" - read -r reply_to_prompt - fi - - case "${reply_to_prompt}" in - [Yy] | [Yy][Ee][Ss] ) - : # Do nothing - ;; - * ) - # If other input then Yes, abort and call error clean-up function - printf "%bRemoval cancelled.\\n" "${prefix_warning}" 1>&2 - remove_ErrorCleanUp - exit 130 - ;; - esac - - return 0 -} - - -remove_HostsFile() -{ - # Moves the original hosts file (backed-up at /etc/hosts.original) - # to /etc/hosts, replacing the current one - if [ -f "${hosts_file_backup_path}" ]; then - mv "${hosts_file_backup_path}" "${hosts_file_path}" \ - && echo "${prefix}Successfully restored ${hosts_file_path}" - else - # If /etc/hosts.original was not found, abort and call the error clean-up function - printf "%bCan not restore hosts file. Original hosts file does not exist.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - echo "${prefix}Maybe already removed?" 1>&2 - remove_ErrorCleanUp - exit 1 - fi - - return 0 -} - - -remove_PreviousHostsFile() -{ - # If found, remove /etc/hosts.previous - if [ -f "${hosts_file_previous_path}" ]; then - rm "${hosts_file_previous_path}" \ - && echo "${prefix}Removed previous hosts file." - else - echo "${prefix}Previous hosts file does not exist. Ignoring ..." - fi - - return 0 -} - - -# Main function of remove.sh -remove() -{ - printf "%bRemoving Adsorber ...%b\\n" "${prefix_title}" "${prefix_reset}" - remove_Prompt - systemdRemove - crontabRemove - remove_HostsFile - remove_PreviousHostsFile - remove_CleanUp - - return 0 -} diff --git a/src/lib/restore.sh b/src/lib/restore.sh index 82dd9ab..ec9250e 100755 --- a/src/lib/restore.sh +++ b/src/lib/restore.sh @@ -21,20 +21,22 @@ # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# remove_CleanUp src/lib/remove.sh -# remove_ErrorCleanUp src/lib/remove.sh +# ---function:------------ ---function defined in:--- +# cleanUp src/lib/cleanup.sh +# errorCleanUp src/lib/cleanup.sh +# update_PreviousHostsFile src/lib/update.sh # shellcheck disable=SC2154 restore_HostsFile() { if [ -f "${hosts_file_backup_path}" ]; then + update_PreviousHostsFile # Copy /etc/hosts.original to /etc/hosts, replacing the current one cp "${hosts_file_backup_path}" "${hosts_file_path}" \ || { printf "%bCouldn't restore %s.%b" "${prefix_fatal}" "${hosts_file_path}" "${prefix_reset}" - remove_ErrorCleanUp + errorCleanUp exit 1 } @@ -42,8 +44,8 @@ restore_HostsFile() printf "%bTo reapply please run 'adsorber update'.\\n" "${prefix}" else # If /etc/hosts.previous was not found, abort and call error clean-up function - printf "%bCan't restore hosts file. Original hosts file does not exist.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - remove_ErrorCleanUp + printf "%bCan't restore original hosts file. Original hosts file does not exist.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + errorCleanUp exit 1 fi @@ -56,7 +58,7 @@ restore() { printf "%bRestoring %s ...%b\\n" "${prefix_title}" "${hosts_file_path}" "${prefix_reset}" restore_HostsFile - remove_CleanUp + cleanUp return 0 } diff --git a/src/lib/revert.sh b/src/lib/revert.sh index 1e8fdab..e73232a 100755 --- a/src/lib/revert.sh +++ b/src/lib/revert.sh @@ -11,19 +11,19 @@ # The following variables are declared globally. # If you run this file independently following variables need to be set: -# ---variable:---------- ---default value:-- ---declared in:---------------- -# hosts_file_path /etc/hosts src/lib/config.sh, adsorber.conf -# hosts_file_previous_path /etc/hosts.previous src/lib/config.sh, adsorber.conf -# prefix ' ' (two spaces) src/lib/colours.sh -# prefix_fatal '\033[0;91mE ' src/lib/colours.sh -# prefix_reset \033[0m src/lib/colours.sh -# prefix_title \033[1;37m src/lib/colours.sh +# ---variable:------------ ---default value:-- ---declared in:---------------- +# hosts_file_path /etc/hosts src/lib/config.sh, adsorber.conf +# hosts_file_previous_path /etc/hosts.previous src/lib/config.sh, adsorber.conf +# prefix ' ' (two spaces) src/lib/colours.sh +# prefix_fatal '\033[0;91mE ' src/lib/colours.sh +# prefix_reset \033[0m src/lib/colours.sh +# prefix_title \033[1;37m src/lib/colours.sh # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# remove_CleanUp src/lib/remove.sh -# remove_ErrorCleanUp src/lib/remove.sh +# --function:-- ---function defined in:--- +# cleanUp src/lib/cleanup.sh +# errorCleanUp src/lib/cleanup.sh # shellcheck disable=SC2154 @@ -34,7 +34,7 @@ revert_HostsFile() cp "${hosts_file_previous_path}" "${hosts_file_path}" \ || { printf "%bCouldn't revert %s.%b" "${prefix_fatal}" "${hosts_file_path}" "${prefix_reset}" - remove_ErrorCleanUp + errorCleanUp exit 1 } @@ -44,8 +44,8 @@ revert_HostsFile() printf "%bSuccessfully reverted %s.\\n" "${prefix}" "${hosts_file_path}" else # If /etc/hosts.previous was not found, abort and call error clean-up function - printf "%bCan't revert hosts file. Previous hosts file does not exist.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - remove_ErrorCleanUp + printf "%bCan't revert to previous hosts file. Previous hosts file does not exist.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + errorCleanUp exit 1 fi @@ -58,7 +58,7 @@ revert() { printf "%bReverting %s with %s ...%b\\n" "${prefix_title}" "${hosts_file_path}" "${hosts_file_previous_path}" "${prefix_reset}" revert_HostsFile - remove_CleanUp + cleanUp return 0; } diff --git a/src/lib/install.sh b/src/lib/setup.sh similarity index 70% rename from src/lib/install.sh rename to src/lib/setup.sh index a10ff4d..1784061 100755 --- a/src/lib/install.sh +++ b/src/lib/setup.sh @@ -1,8 +1,5 @@ #!/bin/sh -# TODO: Maybe rename install to init (initialize) because there's already an -# installation into the system (install-to-system.sh) however with a different goal - # Author: stablestud # Repository: https://github.com/stablestud/adsorber # License: MIT, https://opensource.org/licenses/MIT @@ -23,14 +20,14 @@ # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# crontabInstall src/lib/cron/cron.sh -# remove_ErrorCleanUp src/lib/remove.sh -# systemdInstall src/lib/systemd/systemd.sh +# --function:-- ---function defined in:--- +# crontab src/lib/cron/cron.sh +# errorCleanUp src/lib/cleanup.sh +# systemd src/lib/systemd/systemd.sh # shellcheck disable=SC2154 -install_BackupHostsFile() +setup_BackupHostsFile() { # Create a backup, to be able to restore to it later if neccessary if [ ! -f "${hosts_file_backup_path}" ]; then @@ -45,21 +42,21 @@ install_BackupHostsFile() } -install_Prompt() +setup_Prompt() { - # Ask the user if he/she is sure about to install Adsorber + # Ask the user if he/she is sure about to setup Adsorber if [ -z "${reply_to_prompt}" ]; then - printf "%bDo you really want to install Adsorber? [Y/n]: %b" "${prefix_input}" "${prefix_reset}" + printf "%bDo you really want to setup Adsorber? [Y/n]: %b" "${prefix_input}" "${prefix_reset}" read -r reply_to_prompt fi case "${reply_to_prompt}" in - [Yy] | [Yy][Ee][Ss] ) + [Yy] | [Yy][Ee][Ss] | "" ) return 0 ;; * ) - printf "%bInstallation cancelled.\\n" "${prefix_warning}" 1>&2 - remove_ErrorCleanUp + printf "%bSetup cancelled.\\n" "${prefix_warning}" 1>&2 + errorCleanUp exit 130 ;; esac @@ -68,21 +65,21 @@ install_Prompt() } -install_PromptScheduler() +setup_PromptScheduler() { # The user enters interactively what scheduler (Systemd, Cron or none) # should be used to update the hosts file periodically if [ -z "${reply_to_scheduler_prompt}" ]; then - printf "%bWhat scheduler should be used to update the host file automatically? [(S)ystemd/(C)ron/(N)one]: %b" "${prefix_input}" "${prefix_reset}" + printf "%bWhat scheduler should be used to update the host file automatically? [(C)ron/(s)ystemd/(n)one]: %b" "${prefix_input}" "${prefix_reset}" read -r reply_to_scheduler_prompt fi case "${reply_to_scheduler_prompt}" in - [Ss] | [Ss]ystemd | [Ss][Yy][Ss] ) - systemdInstall + [Cc] | [Cc][Rr][Oo][Nn] | [Cc]ron[Jj]ob | [Cc]ron[Tt]ab | [Cc]ronie | "" ) + crontab ;; - [Cc] | [Cc]ron | [Cc]ron[Jj]ob | [Cc]ron[Tt]ab ) - crontabInstall + [Ss] | [Ss]ystemd | [Ss][Yy][Ss] ) + systemd ;; * ) echo "${prefix}Skipping scheduler creation ..." @@ -93,13 +90,13 @@ install_PromptScheduler() } -# Main function when calling installation related tasks -install() +# Main function when calling setup related tasks +setup() { - printf "%bInstalling Adsorber ...%b\\n" "${prefix_title}" "${prefix_reset}" - install_Prompt - install_BackupHostsFile - install_PromptScheduler + printf "%bSetting up Adsorber ...%b\\n" "${prefix_title}" "${prefix_reset}" + setup_Prompt + setup_BackupHostsFile + setup_PromptScheduler return 0 } diff --git a/src/lib/systemd/adsorber.service b/src/lib/systemd/adsorber.service deleted file mode 100755 index c9a6aab..0000000 --- a/src/lib/systemd/adsorber.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Adsorber service to update the hosts file periodically. -Documentation=https://github.com/stablestud/adsorber -After=network.target - -[Service] -Type=oneshot -User=root -#@ExecStart=/some/path/adsorber update@# diff --git a/src/lib/systemd/default-service b/src/lib/systemd/default-service new file mode 100644 index 0000000..ecac1cf --- /dev/null +++ b/src/lib/systemd/default-service @@ -0,0 +1,16 @@ +[Unit] +Description=#@frequency@# Adsorber service +Documentation=https://github.com/stablestud/adsorber +After=network.target + +[Service] +Type=oneshot +User=root +ExecStart=#@/some/path/adsorber update@# +StandardInput=null +StandardOutput=syslog+console +StandardError=syslog+console +SyslogIdentifier=Adsorber +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true diff --git a/src/lib/systemd/adsorber.timer b/src/lib/systemd/default-timer old mode 100755 new mode 100644 similarity index 60% rename from src/lib/systemd/adsorber.timer rename to src/lib/systemd/default-timer index bc6f201..f2067af --- a/src/lib/systemd/adsorber.timer +++ b/src/lib/systemd/default-timer @@ -1,11 +1,11 @@ [Unit] -Description=Timer that runs the Adsorber service weekly. +Description=Timer that runs the Adsorber service #@frequency@# Documentation=https://github.com/stablestud/adsorber Requires=network-online.target [Timer] -OnCalendar=weekly -RandomizedDelaySec=3600 +OnCalendar=#@frequency@# +RandomizedDelaySec=600 Persistent=true Unit=adsorber.service diff --git a/src/lib/systemd/systemd.sh b/src/lib/systemd/systemd.sh index 8846fc7..b6410b9 100755 --- a/src/lib/systemd/systemd.sh +++ b/src/lib/systemd/systemd.sh @@ -11,10 +11,12 @@ # The following variables are declared globally. # If you run this file independently following variables need to be set: -# ---variable:------- ---default value:-- ---declared in:--------- +# ---variable:------- ---default value:------------ ---declared in:--------- # executable_dir_path the root dir of the script src/bin/adsorber +# frequency null (not set) src/bin/adsorber # library_dir_path ${executable_dir_path}/../lib src/bin/adsorber # prefix ' ' (two spaces) src/lib/colours.sh +# prefix_input ' ' (two spaces) src/lib/colours.sh # prefix_fatal '\033[0;91mE ' src/lib/colours.sh # prefix_reset \033[0m src/lib/colours.sh # prefix_warning '- ' src/lib/colours.sh @@ -22,59 +24,106 @@ # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# remove_ErrorCleanUp src/lib/remove.sh +# --function:-- ---function defined in:--- +# errorCleanUp src/lib/remove.sh # shellcheck disable=SC2154 -systemdInstall() +systemdSetup() { # Check if the variable systemd_dir_path is valid, if not abort and call error clean-up function if [ ! -d "${systemd_dir_path}" ]; then - printf "%bWrong systemd_dir_path set. Can't access: %s.%b\\n" "${prefix_fatal}" "${systemd_dir_path}" "${prefix_reset}" 1>&2 - echo "${prefix}Is Systemd installed? If not use cron instead." - remove_ErrorCleanUp + printf "%bWrong systemd_dir_path set. Can't access: %s.%b\\n" \ + "${prefix_fatal}" "${systemd_dir_path}" "${prefix_reset}" 1>&2 + + echo "${prefix}Is Systemd installed? If not use Cron instead." + errorCleanUp exit 126 fi - # Remove systemd service if already installed + # Remove systemd service if already present if [ -f "${systemd_dir_path}/adsorber.service" ] || [ -f "${systemd_dir_path}/adsorber.timer" ]; then - echo "${prefix}Removing previously installed systemd services ..." - systemdRemove + echo "${prefix}Removing previous Systemd service ..." + if ! systemdRemove; then + printf "%bSomething failed at updating the Systemd service, aborting ...%b" "${prefix_fatal}" "${prefix_reset}" 1>&2 + errorCleanUp; + exit 1; + fi fi - echo "${prefix}Installing systemd service ..." + echo "${prefix}Setting up ${frequency} Systemd service ..." # Replace the @ place holder line with the location of adsorber and copy # the service to the systemd directory ( /etc/sytemd/system/adsorber.service ) - sed "s|^#@ExecStart=\\/some\\/path\\/adsorber update@#$|ExecStart=${executable_dir_path}\\/adsorber update|g" "${library_dir_path}/systemd/adsorber.service" \ - > "${systemd_dir_path}/adsorber.service" + sed "s|#@\\/some\\/path\\/adsorber update@#|${executable_dir_path}\\/adsorber update --noformatting|g" "${library_dir_path}/systemd/default-service" \ + | sed "s/#@frequency@#/${frequency}/g" \ + > "${systemd_dir_path}/adsorber.service" + # Copy the systemd timer to /etc/systemd/system/adsorber.timer, timer is the clock that triggers adsorber.service - cp "${library_dir_path}/systemd/adsorber.timer" "${systemd_dir_path}/adsorber.timer" + sed "s/#@frequency@#/${frequency}/g" "${library_dir_path}/systemd/default-timer" \ + > "${systemd_dir_path}/adsorber.timer" - chmod u=rwx,g=rx,o=rx "${systemd_dir_path}/adsorber.service" "${systemd_dir_path}/adsorber.timer" + chmod u=rw,g=r,o=r "${systemd_dir_path}/adsorber.service" "${systemd_dir_path}/adsorber.timer" chown root:root "${systemd_dir_path}/adsorber.service" "${systemd_dir_path}/adsorber.timer" # Enable the systemd service and enable it to start at boot-up systemctl daemon-reload 2>/dev/null \ && systemctl enable adsorber.timer 2>/dev/null - if ! systemctl start adsorber.timer 2>/dev/null; then - # Systemd couldn't be run, probably it's a systemd-less system like Gentoo - printf "%bCouldn't start systemd service.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - echo "${prefix}Is Systemd installed? If not use cron instead." - systemdRemove - remove_ErrorCleanUp - exit 126 - fi + if ! systemctl start adsorber.timer 2>/dev/null; then + # Systemd couldn't be run, probably it's a systemd-less system like Gentoo + printf "%bCouldn't start systemd service.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 + echo "${prefix}Is Systemd installed? If not use Cron instead." + systemdRemove + errorCleanUp + exit 126 + fi - # Make known that we have installed the systemd service in this run, - # if we fail now, systemd will be also removed (see remove_ErrorCleanUp) - readonly installed_scheduler="systemd" + # Make known that we have setup the systemd service in this run, + # if we fail now, systemd will be also removed (see errorCleanUp) + readonly setup_scheduler="systemd" echo "${prefix}Initialized Systemd service ..." +} - return 0 + +systemdPromptFrequency() +{ + if [ -z "${frequency}" ]; then + printf "%bHow often should the service run? [(h)ourly/(d)aily/(W)eekly/(m)onthly/(q)uarterly]: " "${prefix_input}" + read -r _freq_input + + case "${_freq_input}" in + [Hh] | [Hh][Oo][Uu][Rr] | [Hh][Oo][Uu][Rr][Ll][Yy] ) + readonly frequency="hourly" + ;; + [Dd] | [Dd][Aa][Yy] | [Dd][Aa][Ii][Ll][Yy] ) + readonly frequency="daily" + ;; + [Ww] | "" | [Ww][Ee][Ee][Kk] | [Ww][Ee][Ee][Kk][Ll][Yy] ) + readonly frequency="weekly" + ;; + [Mm] | [Mm][Oo][Nn][Tt][Hh] | [Mm][Oo][Nn][Tt][Hh][Ll][Yy] ) + readonly frequency="monthly" + ;; + [Yy] | [Yy][Ee][Aa][Rr] | [Yy][Ee][Aa][Rr][Ll][Yy] | \ + [Aa] | [Aa][Nn][Nn][Uu][Aa][Ll] | [Aa][Nn][Nn][Uu][Aa][Ll][Ll][Yy] ) + readonly frequency="yearly" + ;; + [Qq] | [Qq][Uu][Aa][Rr][Tt][Ee][Rr] | [Qq][Uu][Aa][Rr][Tt][Ee][Rr][Ll][Yy] ) + readonly frequency="quarterly" + ;; + [Ss] | [Ss][Ee][Mm][Ii] | [Ss][Ee][Mm][Ii][Aa][Nn][Nn][Uu][Aa][Ll][Ll][Yy] ) + readonly frequency="semiannually" + ;; + * ) + echo "${prefix_warning}Frequency '${_freq_input}' not understood.${prefix_reset}" 1>&2 + systemdPromptFrequency + ;; + esac + + unset _freq_input + fi } @@ -82,7 +131,7 @@ systemdRemove() { if [ -f "${systemd_dir_path}/adsorber.service" ] || [ -f "${systemd_dir_path}/adsorber.timer" ]; then - # Disable timer and add "${prefix}" to the output stream, to format it so it can fit the Adsorber 'style' + # Disable timer systemctl stop adsorber.timer 2>/dev/null systemctl disable adsorber.timer 2>/dev/null \ @@ -91,9 +140,11 @@ systemdRemove() systemctl disable adsorber.service 2>/dev/null 1>&2 # This service is not enabled by default # Remove leftover service files. - rm "${systemd_dir_path}/adsorber.timer" "${systemd_dir_path}/adsorber.service" \ + rm "${systemd_dir_path}/adsorber.timer" "${systemd_dir_path}/adsorber.service" 2>/dev/null 1>&2 \ || { - printf "%bCouldn't remove systemd service files at %s%b\\n." "${prefix_fatal}" "${systemd_dir_path}" "${prefix_reset}" 1>&2 + printf "%bCouldn't remove Systemd service files at %s%b\\n." \ + "${prefix_fatal}" "${systemd_dir_path}" "${prefix_reset}" 1>&2 + return 1 } @@ -104,6 +155,11 @@ systemdRemove() else echo "${prefix}Systemd service not installed. Skipping ..." fi +} - return 0 + +systemd() +{ + systemdPromptFrequency + systemdSetup } diff --git a/src/lib/update.sh b/src/lib/update.sh index a10dd81..3c35714 100755 --- a/src/lib/update.sh +++ b/src/lib/update.sh @@ -11,7 +11,7 @@ # The following variables are declared globally. # If you run this file independently following variables need to be set: -# ---variable:---------- ---default value:------------ ---declared in:---- +# ---variable:-------------- ---default value:------------ ---declared in:---- # config_dir_path ${executable_dir_path}/../../ src/bin/adsorber # hosts_file_backup_path /etc/hosts.original src/lib/config.sh, adsorber.conf # hosts_file_path /etc/hosts src/lib/config.sh, adsorber.conf @@ -28,16 +28,16 @@ # prefix_title \033[1;37m src/lib/colours.sh # prefix_warning '- ' src/lib/colours.sh # primary_list blacklist src/lib/config.sh, adsorber.conf -# reply_to_force_prompt Null (not set) src/lib/install.sh, src/bin/adsorber +# reply_to_force_prompt Null (not set) src/lib/setup.sh, src/bin/adsorber # tmp_dir_path /tmp/adsorber src/bin/adsorber # use_partial_matching true src/lib/config.sh, adsorber.conf # version 0.2.2 or similar src/bin/adsorber # The following functions are defined in different files. # If you run this file independently following functions need to be emulated: -# ---function:----- ---function defined in:--- -# remove_CleanUp src/lib/remove.sh -# remove_ErrorCleanUp src/lib/remove.sh +# --function:-- ---function defined in:--- +# cleanUp src/lib/cleanup.sh +# errorCleanUp src/lib/cleanup.sh # shellcheck disable=SC2154 @@ -50,7 +50,7 @@ update_CheckBackupExist() # hostname association with 127.0.0.1 and localhost will be lost. # The user may interactively decide here wheter to proceed or not. if [ -z "${reply_to_force_prompt}" ]; then - printf "%bBackup of %s does not exist. To backup run 'adsorber install'.%b\\n" "${prefix_fatal}" "${hosts_file_path}" "${prefix_reset}" 1>&2 + printf "%bBackup of %s does not exist. To backup run 'adsorber setup'.%b\\n" "${prefix_fatal}" "${hosts_file_path}" "${prefix_reset}" 1>&2 printf "%bIgnore issue and continue? (May break your hostfile, not recommended) [YES/n]: %b" "${prefix_input}" "${prefix_reset}" read -r reply_to_force_prompt fi @@ -61,7 +61,7 @@ update_CheckBackupExist() ;; * ) printf "%bAborted.\\n" "${prefix_warning}" 1>&2 - remove_ErrorCleanUp + errorCleanUp exit 130 ;; esac @@ -94,7 +94,7 @@ update_ReadSourceList() if [ ! -s "${config_dir_path}/sources.list" ]; then if [ ! -s "${config_dir_path}/blacklist" ]; then - printf "%bMissing 'sources.list' and blacklist. To fix run '%s install'.%b\\n" "${prefix_fatal}" "${0}" "${prefix_reset}" 1>&2 + printf "%bMissing 'sources.list' and blacklist. To fix run 'adsorber setup'.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 exit 127 fi @@ -195,7 +195,7 @@ update_FetchSources() else printf "%bNeither curl nor wget installed. Can't continue.%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - remove_ErrorCleanUp + errorCleanUp exit 2 fi @@ -210,7 +210,7 @@ update_FetchSources() elif [ "${ignore_download_error}" = "false" ] && [ "${_successful_count}" -ne "${_total_count}" ]; then printf "%bCouldn't fetch all hosts sources [%d/%d]. Aborting ...\\n" "${prefix_warning}" "${_successful_count}" "${_total_count}" 1>&2 - remove_ErrorCleanUp + errorCleanUp exit 1 else printf "%bSuccessfully fetched %d out of %d hosts sources.%b\\n" "${prefix_info}" "${_successful_count}" "${_total_count}" "${prefix_reset}" @@ -324,7 +324,7 @@ update_IsCacheEmpty() { if [ ! -s "${tmp_dir_path}/cache" ]; then printf "%bNothing to apply.\\n" "${prefix_warning}" 1>&2 - remove_ErrorCleanUp + cleanUp exit 1 fi @@ -381,7 +381,7 @@ update_PreviousHostsFile() cp "${hosts_file_path}" "${hosts_file_previous_path}" \ || { printf "%bCouldn't create previous hosts file at %s%b\\n" "${prefix_fatal}" "${hosts_file_previous_path}" "${prefix_reset}" - remove_ErrorCleanUp + errorCleanUp exit 1 } @@ -401,7 +401,7 @@ update_ApplyHostsFile() cp "${tmp_dir_path}/hosts" "${hosts_file_path}" \ || { printf "%b" "${prefix_fatal}Couldn't apply hosts file. Aborting.${prefix_reset}\\n" 1>&2 - remove_ErrorCleanUp + errorCleanUp exit 126 } @@ -423,11 +423,14 @@ update() update_ReadWhiteList if update_ReadSourceList; then - update_FetchSources - update_FilterDomains "fetched" "fetched-filtered" - update_SortDomains "fetched-filtered" "fetched-sorted" - - cp "${tmp_dir_path}/fetched-sorted" "${tmp_dir_path}/cache" + if update_FetchSources; then + update_FilterDomains "fetched" "fetched-filtered" + update_SortDomains "fetched-filtered" "fetched-sorted" + cp "${tmp_dir_path}/fetched-sorted" "${tmp_dir_path}/cache" + else + # Create empty cache file for the ad-domains. + touch "${tmp_dir_path}/cache" + fi else # Create empty cache file for the ad-domains. touch "${tmp_dir_path}/cache" @@ -444,7 +447,7 @@ update() ;; * ) printf "%bWrong primary_list set in adsorber.conf. Choose either 'whitelist' or 'blacklist'%b\\n" "${prefix_fatal}" "${prefix_reset}" 1>&2 - remove_ErrorCleanUp + errorCleanUp exit 127 ;; esac @@ -453,7 +456,7 @@ update() update_BuildHostsFile update_PreviousHostsFile update_ApplyHostsFile - remove_CleanUp + cleanUp return 0 } diff --git a/src/share/components/hosts_header b/src/share/components/hosts_header old mode 100755 new mode 100644 index e7acf4f..4a47fc3 --- a/src/share/components/hosts_header +++ b/src/share/components/hosts_header @@ -5,6 +5,6 @@ # and run 'adsorber update' to apply your changes. # Or else your changes will be overwritten by Adsorber once a week. # -# By default, the domains will be updated once a week. +# By default, the domains will be updated once a week if not other specified. # For further information please run 'adsorber --help' # Or visit: https://github.com/stablestud/adsorber diff --git a/src/share/components/hosts_title b/src/share/components/hosts_title old mode 100755 new mode 100644 index 92ce02c..8587949 --- a/src/share/components/hosts_title +++ b/src/share/components/hosts_title @@ -1,2 +1,2 @@ -# Following #@blocked@# domain(s) were inserted by Adsorber and are blocking advertisement: +# Following #@blocked@# domain(s) were inserted by Adsorber and are being blocked: diff --git a/src/share/default/default-adsorber.conf b/src/share/default/default-adsorber.conf old mode 100755 new mode 100644 index 21eaae1..d3d7792 --- a/src/share/default/default-adsorber.conf +++ b/src/share/default/default-adsorber.conf @@ -1,7 +1,7 @@ #@ Config file for Adsorber v?.?.? (DO NOT EDIT, WILL BE OVERWRITTEN BY SCRIPT)@ # -# To reset the config file just delete it and run 'adsorber install', -# a new config file will be created. +# To reset the config file just delete it and run 'adsorber setup', +# a new config file will be created. # # For more information please visit: https://github.com/stablestud/Adsorber # Don't hesitate to create issues and pull-requests. @@ -11,7 +11,7 @@ # Defines what list (either whitelist or blacklist) has the priority. # # For example: if 'blacklist' is set, the blacklist will overwrite -# the whitelist. It'll block the connection to a particular host from the +# the whitelist. It'll block the connection to a particular host listed in the # blacklist even if it's allowed in the whitelist. # # Possible values: whitelist, blacklist @@ -23,7 +23,7 @@ primary_list=blacklist ## use_partial_matching # Defines whether the WHITELIST includes sub-domains or not. # -# For example: You white listed the domain wholesome-ads.com, if the value +# For example: You whitelisted the domain wholesome-ads.com, if the value # is set to 'true' all it's sub-domains like annoying.wholesome-ads.com will be # also allowed. To disable this set the value to 'false'. # @@ -37,12 +37,12 @@ use_partial_matching=true ## ignore_download_error -# If set to false, we'll only apply the hosts file if all hosts sources +# If set to false, it'll only apply the hosts file if all hosts sources # could be reached. # -# For example: You have a few host sources but one is not responding, to not -# lose the already installed domains from the particular source, the script -# won't continue. +# For example: You have two host sources but one is not responding, to not +# lose the already installed domains from the failing source, the script +# won't continue if it was set to 'false'. # # Possible values: true, false # Default value: true @@ -55,6 +55,9 @@ ignore_download_error=true # Adsorber will prioritize the root users environment variables of 'http_proxy' # and 'https_proxy' over the ones specified here. # +# Please note that your ordinary user 'http(s)_proxy' environmental variables won't affect Adsorber +# as it doesn't run as user but as root user. +# # Possible value: address:port (e.g proxy:8080, 127.0.0.1:9050) # Default value: Null (not set) # @@ -71,8 +74,8 @@ https_proxy= ## hosts_file_path -# hosts_file_pat is used to set the path to the systems hosts file. -# Change if your system uses an other file or path. +# hosts_file_path is used to set the path to the systems hosts file. +# Change if your system uses a different file or path. # # Default value: /etc/hosts @@ -80,17 +83,17 @@ hosts_file_path=/etc/hosts ## hosts_file_backup_path -# hosts_file_backup_path is used to set the filename and the path to the -# backup of the hosts file to be created by Adsorber in the install process. -# To simply create a new backup run 'adsorber install' +# Defines the backup location of the original hosts file created by the operating system. +# If no backup was created you can do this by running 'adsorber setup'. # # Default value: /etc/hosts.original hosts_file_backup_path=/etc/hosts.original -## hosts_file_previous_enable, hosts_file_previous_path ## -# Info goes here +## hosts_file_previous_enable, hosts_file_previous_path +# Set where and if the previous hosts file should be backed-up before creating +# a new one. To return back to the previous host file run 'adsorber revert'. # # Possible values for 'hosts_file_previous_enable': true, false # Default value for 'hosts_file_previous_enable': true @@ -101,33 +104,13 @@ hosts_file_previous_enable=true hosts_file_previous_path=/etc/hosts.previous -## crontab_dir_path -# This defines the directory in which we'll set the crontab. -# Used to create a scheduler which supplies the hosts file regulary with -# new ad-domains. -# -# In the default setting it'll update once a week. You can change this behavior -# with setting another directory, for example /etc/cron/daily to update the -# hosts file daily. -# -# Possible value: /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, -# /etc/cron.monthly/, or any other directory which it's contents will be -# executed as a script regulary. -# -# Default value: /etc/cron.weekly/ - -crontab_dir_path=/etc/cron.weekly/ - - ## systemd_dir_path # This defines the directory in which we'll place the systemd files. # Used to create a scheduler which supplies the hosts file regulary with -# new ad-domains. Change if your system has an other path. +# new ad-domains. Only change if your system has an other path. # -# In the default setting it'll update once a week. To change this behavior you -# need to change adsorber.timer's 'OnCalendar' setting to another period. -# The file can be found at systemd_dir_path, to change it before placement go -# into the scripts root directory and edit bin/systemd/adsorber.timer +# Note: if you don't have systemd you can leave this setting by its default value. +# Use in this case cronjob instead. # # Default value: /etc/systemd/system/ diff --git a/src/share/default/default-blacklist b/src/share/default/default-blacklist old mode 100755 new mode 100644 diff --git a/src/share/default/default-sources.list b/src/share/default/default-sources.list old mode 100755 new mode 100644 diff --git a/src/share/default/default-whitelist b/src/share/default/default-whitelist old mode 100755 new mode 100644 index 117af7a..284a228 --- a/src/share/default/default-whitelist +++ b/src/share/default/default-whitelist @@ -1,10 +1,10 @@ # Whitelist # Use to allow domains, even if they are blocked from some hosts sources. -# By default, the blacklist overwrites the whitelist. This can be changed in adsorber.conf. +# However the blacklist overwrites the whitelist by default. This can be changed in adsorber.conf. # -# Note: the whitelist uses partial matching. Means if you allow adserver.tld +# Note: the whitelist uses partial matching. Means if you allow adserver.tld, # all its subdomains like ad1.adserver.tld also will be allowed. -# (Can be changed in adsorber.conf by editing 'use_partial_matching') +# (Can be changed in adsorber.conf by changing 'use_partial_matching' to false) # # Entries must begin with either 127.0.0.1 or 0.0.0.0