#!/bin/bash #=============================================================================== # # DIRECTORY: # --- # # FILE: # ./casualscripter_functions.sh # # USAGE: # This is a library for some scripts. # # OPTIONS: # none # # EXIT STATES: # 101 = logfile not set # 102 = dir for logfile not writable # 103 = logfile already exists but is not writable # 104 = a wanted binary is not installed # # DESCRIPTION: # Global configuration and functions for scripts. # # REQUIREMENTS: # which, uname, basename, ps, grep, awk, sed, dirname, tee, openssl, ... # # BUGS: # --- # # NOTES: # Tested on: # - Debian GNU/Linux 8.x + bash, zsh, ksh, busybox ash & dash # - ArchLinux + bash, zsh, ksh, busybox ash & dash # - Linux Mint 18 (Cinnamon) + bash, zsh, ksh, busybox ash & dash # - FreeBSD 11 + bash, zsh & busybox ash # - OS X (10.11.6) + bash (sh) and zsh # ! (t)csh is NOT supported ! # # AUTHOR: # Patrick Neumann, patrick@neumannsland.de # # COMPANY: # (privately) # # VERSION: # 1.0 # # LINK TO THE MOST CURRENT VERSION: # https://vcs.neumannsland.de/casualscripter/web_site_monitor # # CREATED: # 2016-10-18 # # COPYRIGHT (C): # 2016 - Patrick Neumann # # LICENSE: # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # WARRANTY: # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # NOTE: # --- # # TODO: # --- # # HISTORY: # 1.0 - Patrick Neumann - Initial (for the trainers eyes only) release # #=============================================================================== # Relative paths are more portable but less secure. # Absolute paths are more secure but less portable. readonly BIN_WHICH="$( which "which" )" readonly BIN_UNAME="$( ${BIN_WHICH} "uname" )" readonly BIN_BASENAME="$( ${BIN_WHICH} "basename" )" readonly BIN_PS="$( ${BIN_WHICH} "ps" )" readonly BIN_GREP="$( ${BIN_WHICH} "grep" )" readonly BIN_AWK="$( ${BIN_WHICH} "awk" )" readonly BIN_SED="$( ${BIN_WHICH} "sed" )" readonly BIN_DIRNAME="$( ${BIN_WHICH} "dirname" )" readonly BIN_TEE="$( ${BIN_WHICH} "tee" )" readonly BIN_OPENSSL="$( ${BIN_WHICH} "openssl" )" # Changeable defaults: DEFAULT_SHELL="bash" ECHO_FUNC="display" #------------------------------------------------------------------------------- # Detect operating system name. #------------------------------------------------------------------------------- readonly OS_NAME="$( ${BIN_UNAME} -s )" # "sed -E" on macOS is the same as "sed -r" on Linux if [ "${OS_NAME}" = "Darwin" -o "${OS_NAME}" = "FreeBSD" ] ; then readonly SED_EXT_REGEXP="-E" readonly DATE_DISPLAY="-j -f %s " readonly DARWIN_FIND_REGEXP_TYPE="-E " else readonly SED_EXT_REGEXP="--regexp-extended" readonly DATE_DISPLAY="-d @" readonly LINUX_FIND_REGEXP_TYPE="-regextype posix-extended " fi #------------------------------------------------------------------------------- # Detect the shell in which we are running. #------------------------------------------------------------------------------- readonly PROCESS="$( ${BIN_BASENAME} "$( ${BIN_PS} -axco pid,command \ | ${BIN_GREP} "$$" \ | ${BIN_GREP} -v "grep" \ | ${BIN_AWK} '{ print $2; }' )" )" # Why conditinal command should be prefered over test: # https://google-styleguide.googlecode.com/svn/trunk/shell.xml#Test,_[_and_[[ # and why you don't, if you would support "dash": # http://mywiki.wooledge.org/Bashism if [ "${PROCESS}" = "$( ${BIN_BASENAME} "${0}" )" ] ; then readonly CURRENT_SHELL="${DEFAULT_SHELL}" else readonly CURRENT_SHELL="${PROCESS}" fi # Linux can have alle shells and "/bin/echo" has no limitations. # Darwin (14.5.0) has bash 3.2.57, zsh 5.0.5, ksh 93 and tcsh 6.17.00 # - kshs and tcshs builtin echo does not support "-e" and/or "-n"! # - "/bin/echo" does not support "-e"! # FreeBSD can have all shells, but "/bin/echo" has the same limitations! # Solution: use printf instead! # Worth readable Link: http://hyperpolyglot.org/unix-shells#echo-note if [ "${CURRENT_SHELL}" = "zsh" ] ; then # zsh does not split a string into words separated by spaces by default! setopt shwordsplit # zshs "which" find the builtin without "-p"! readonly BIN_PRINTF="$( which -p printf )" else readonly BIN_PRINTF="$( which printf )" fi #=== FUNCTION ================================================================== # NAME: trim # DESCRIPTION: Remove leading and trailing whitespace characters from a string. # PARAMETER 1: string #------------------------------------------------------------------------------- # SOMETIMES NEEDED FOR CONFIGURATION! #=============================================================================== # Do not use "function" if you want to support dash: # http://mywiki.wooledge.org/Bashism trim () { var="${1}" var="${var#"${var%%[![:space:]]*}"}" var="${var%"${var##*[![:space:]]}"}" ${BIN_PRINTF} "${var}" } #=== FUNCTION ================================================================== # NAME: logfile_checks # DESCRIPTION: Checks if a logfile is set and can be created. # PARAMETERS: none (a global var will be used.) #=============================================================================== logfile_checks () { if [ -z "${LOG_FILE}" ] ; then ${BIN_PRINTF} "\033[01;31;40mERROR: logfile not set... EXIT!!!\033[00m\n" exit 101 fi if ! [ -w "$( ${BIN_DIRNAME} "${LOG_FILE}" )" ] ; then ${BIN_PRINTF} "\033[01;31;40mERROR: dir for logfile not writable... EXIT!!!\033[00m\n" exit 102 fi if [ -e "${LOG_FILE}" ] ; then if ! [ -w "${LOG_FILE}" ] ; then ${BIN_PRINTF} "\033[01;31;40mERROR: logfile already exists but is not writable... EXIT!!!\033[00m\n" exit 103 fi fi } #=== FUNCTION ================================================================== # NAME: overwrite # DESCRIPTION: Check if the custom file already exists and ask for overwriting # or exit. # PARAMETER 1: custom file # PARAMETER 2: file type #=============================================================================== overwrite() { if [ -e "${1}" ] ; then ${BIN_PRINTF} "\n${2} does already exist, overwrite? \ (type YES in UPPER letters and hit return!) : " read -r answer if [ "${answer}" != "YES" ] ; then ${BIN_PRINTF} "\033[01;34;40mHINT: move the old ${2} to a save place and try again... EXIT!!!\033[00m\n" exit 0 fi # clear logfile ${BIN_PRINTF} "" > "${LOG_FILE}" fi } #=== FUNCTION ================================================================== # NAME: display # DESCRIPTION: Wrapper for "echo -n -e". # PARAMETER 1: message (string) #=============================================================================== display () { ${BIN_PRINTF} "${1}" } #=== FUNCTION ================================================================== # NAME: log # DESCRIPTION: Wrapper for "echo -n -e" incl. redirection into logfile. # PARAMETER 1: message (string) #=============================================================================== log () { logfile_checks ${BIN_PRINTF} "${1}" >> "${LOG_FILE}" } #=== FUNCTION ================================================================== # NAME: display_and_log # DESCRIPTION: Wrapper for "echo -n -e" incl. output to stdout AND redirection # into logfile. # PARAMETER 1: message (string) #=============================================================================== display_and_log () { logfile_checks ${BIN_PRINTF} "${1}" | ${BIN_TEE} -a "${LOG_FILE}" } #=== FUNCTION ================================================================== # NAME: quiet # DESCRIPTION: Wrapper for "echo -n -e" incl. redirection into "nirvana". # PARAMETER 1: message (string) #=============================================================================== quiet () { ${BIN_PRINTF} "${1}" > /dev/null } #=== FUNCTION ================================================================== # NAME: error # DESCRIPTION: Display red error messages starting with "ERROR:". # PARAMETER 1: message (string) #=============================================================================== error () { # TODO: stderr!? "${ECHO_FUNC}" "\033[01;31;40mERROR: ${1}!!!\033[00m\n" } #=== FUNCTION ================================================================== # NAME: hint # DESCRIPTION: Display blue hint messages starting with "HINT:". # PARAMETER 1: message (string) #=============================================================================== hint () { "${ECHO_FUNC}" "\033[01;34;40mHINT: ${1}!\033[00m\n" } #=== FUNCTION ================================================================== # NAME: success # DESCRIPTION: Display green success messages starting with "SUCCESS:". # PARAMETER 1: message (string) #=============================================================================== success () { "${ECHO_FUNC}" "\033[01;32;40mSUCCESS: ${1}!\033[00m\n" } #=== FUNCTION ================================================================== # NAME: assign_binary # DESCRIPTION: ... # PARAMETER 1: string #=============================================================================== assign_binary () { if [ ${1:0:1} = "/" ] ; then # Absolute paths are more secure but less portable. if ! [ -e "${1}" ] ; then error "${1} not installed" exit 104 fi local var="BIN_$( ${BIN_PRINTF} "$( ${BIN_BASENAME} "${1}" )" | tr [:lower:] [:upper:] )" eval "readonly $var=\${1}" else # Relative paths are more portable but less secure. local var="BIN_$( ${BIN_PRINTF} "${1}" | tr [:lower:] [:upper:] )" eval "readonly $var=\$( ${BIN_WHICH} "${1}" )" if [ -z "$( eval "${BIN_PRINTF} \$$var" )" ] ; then error "${1} not installed" exit 104 fi fi } # Do not use "exit" at the end of a library!