#---------------------------------------------------------------------------- # /var/install/include/jedlib - library for eisfair scripts # # Copyright (c) 2001-2020 The Eisfair Team, team(at)eisfair(dot)org # # Creation: 2006-03-29 jed # Last Update: $Id: jedlib 78541 2020-06-24 14:19:48Z jed $ # # Usage: jed-lib --version - print jedlib version number # # 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 2 of the License, or # (at your option) any later version. #---------------------------------------------------------------------------- _jedlib_date=`/bin/date +%Y-%m-%d` _jedlib_time=`/bin/date +%H:%M:%S` #---------------------------------------------------------------------------- # interface description #---------------------------------------------------------------------------- # Variables: # configlog_file This variable needs to contain a valid path # to the configlog file. # force_quiet_run This variable need to be set to 'true' or '1' # to suppress screen output # # Routines: # update_jedlib() update jedlib function_library # # myecho() special echo command which allows to suppress # screen output based on the global variable # ${force_quiet_run} and the '--force-output' # switch. # myanykey() special anykey command which allows to suppress # a hard key input and replace it by a delay based # on the global variable $force_quiet_run and the # '--force-input' switch. # # install_config() install/update package configuration file # # write_to_config_log() writes a message to config log # compress_config_log() compress config log to given number of configuration logs # display_config_log() display config log file if it exists # # print_short_header() print a short file header which references to # the config file # # insert_date() insert date_stamp into text string # insert_hostname() insert hostname into text string # # trim_spaces() return string with no spaces # # get_accessrights() get file/directory ownership and access rights # set_accessrights() set file/directory ownership and access rights # # rand_char() return random character # rand_string() return random string # # shorten_string() return shortened string # # get_last_day_of_month() return date of last day of the month # get_yesterday() return date of previous day # get_tomorrow() return date of next day # get_diff_days() return number of days between two dates # get_diff_dates() return number of years, month, days, hours, # minutes and seconds between two dates # sec_to_formated_time() return formated time "[HH:]MM:SS" from pure seconds # formated_time_to_sec() return seconds from formated time "[HH:]MM:SS" # # unit_to_numeric() return pure integer value from value incl. unit (k/M/G/T) # numeric_to_unit() return value incl. unit (k/M/G/T/P) from pure integer # # abs_path() return the absolute path to a given file # # delay_script_exec() delay script execution, except the current script # is the first one on the list # # format_version() format version number, e.g. 1.002.3. -> 1.2.3.0 # compare_version() compare two version numbers, e.g. 1.0.2 and 1.1.0 # # imaputf7_encode() return IMAP-UTF7 encoded string from normal string # imaputf7_decode() return normal string from IMAP-UTF7 encoded string # # mime_encode() return a MIME-encoded string (quoted printable/Base64) # mime_decode() return a decoded MIME string # # Functions: # is_root() check if root equivalent user # is_numeric() check if numeric value # is_date() check if date value [YYYY-MM-DD] # is_time() check if time value [HH:MM:SS] # # called_from_install() check if script was called from the install # process # # host_exists() check if host exists # get_ipaddr_port() return ip address type, ip address, tcp port, or # all three options in one string # #---------------------------------------------------------------------------- #============================================================================ # only include this file once #============================================================================ if [ "$_JEDLIB" != 'true' ] then _JEDLIB='true' if [ "$1" = "version" -o "$1" = '-version' -o "$1" = '--version' ] then _jedlib_version=`grep -E "Last Update *:" $0 | sed "s/.*jedlib[-_.a-z0-9]* //g" | cut -d' ' -f1` echo ${_jedlib_version} exit 0 fi # # update_jedlib # ------------- # # update shared jedlib library file # # Parameters: $1 name of package # update_jedlib () { local _uj_destfile local _uj_destver local _uj_packfile local _uj_srcfile local _uj_srcver _uj_srcfile=/var/install/include/jedlib.${1} _uj_destfile=/var/install/include/jedlib # extract jedlib from archive _uj_packfile=`find /tmp -maxdepth 1 -type l -name "${1}.*" ! -name "*.info" | head -n1` if [ -n "${_uj_packfile}" ] then if [ -s "${_uj_packfile}" ] then tar xjf ${_uj_packfile} var/install/include/jedlib.${1} -C / fi fi if [ -f ${_uj_srcfile} ] then # src file exists, go on ... if [ -f ${_uj_destfile} ] then # file exists - check versions _uj_srcver=`/bin/sh ${_uj_srcfile} version` _uj_destver=`/bin/sh ${_uj_destfile} version` if [ -n "${_uj_destver}" ] then # version number exists - compare version numbers if [ `echo "${_uj_srcver} > ${_uj_destver}" | bc` -eq 1 ] then # update file echo "updating shared library file (${_uj_destver}->${_uj_srcver}) ..." mv -v ${_uj_srcfile} ${_uj_destfile} fi else # no version number exists - update file echo "updating shared library file ..." mv -v ${_uj_srcfile} ${_uj_destfile} fi else # file doesn't exist - update file echo "updating shared library file ..." mv -v ${_uj_srcfile} ${_uj_destfile} fi # make sure that the file is world readable chmod 644 ${_uj_destfile} # remove copy of shared library file rm -f ${_uj_srcfile} fi } # # myecho # ------ # # special echo command which allows to suppress screen output # based on the global variable '$force_quiet_run'. # # Parameters: $1/$2 '--package <package>' and optionally # '--force-output' and/or # $3-$n normal mecho switches and text # # Output: output text # myecho () { local _me_exit local _me_force_output local _me_outstr local _me_switch local _me_quiet if [ "${_EISLIB}" != 'true' ] then # load eislib if not already loaded . /var/install/include/eislib fi # check if quiet run has been requested _me_quiet=false if is_numeric "${force_quiet_run}" then if [ ${force_quiet_run} -eq 1 ] then _me_quiet=true fi else if [ -n "${force_quiet_run}" ] then _me_quiet=${force_quiet_run} fi fi _me_exit=0 _me_force_output=0 while [ ${_me_exit} -eq 0 ] do case $1 in *-force-output ) _me_force_output=1 shift ;; *-pack|*-package ) _me_package="$2" shift; shift ;; * ) _me_exit=1 ;; esac done if [ ${_me_force_output} -eq 1 ] then _me_quiet=false else if called_from_install --pack "${_me_package}" then _me_quiet=true fi fi if ! ${_me_quiet:-false} then _me_exit=0 _me_switch='' _me_outstr='' while [ ${_me_exit} -eq 0 ] do case $1 in -n|*-std|*stdbr|*-info|*-warn|*-error|*-link|*-ok|*-fail|*-tty|*-html|*-file ) _me_switch="${_me_switch}$1 " shift ;; * ) _me_outstr="$*" _me_exit=1 ;; esac done # be verbose mecho ${_me_switch} "${_me_outstr}" fi } # # myanykey # -------- # # special anykey command which allows to suppress a hard # key input and replace it by a delay based on the global # variable 'force_quiet_run'. # # Parameters: $1 '--package <package>' and optionally # '--force-input' and/or optionally # '--timeout <time>' # myanykey () { local _ma_exit local _ma_force_input local _ma_package local _ma_quiet local _ma_timeout _ma_timeout=3 # check if quiet run has been requested _ma_quiet=false if is_numeric "${force_quiet_run}" then if [ ${force_quiet_run} -eq 1 ] then _ma_quiet=true fi else if [ -n "${force_quiet_run}" ] then _ma_quiet=${force_quiet_run} fi fi _ma_exit=0 _ma_force_input=0 while [ ${_ma_exit} -eq 0 ] do case $1 in *-force-input ) _ma_force_input=1 shift ;; *-pack|*-package ) _ma_package="$2" shift; shift ;; *-timeout ) _ma_timeout="$2" shift; shift ;; * ) _ma_exit=1 ;; esac done if [ ${_ma_force_input} -eq 1 ] then _ma_quiet=false else if called_from_install --pack "${_ma_package}" then _ma_quiet=true fi fi if ${_ma_quiet:-false} then sleep ${_ma_timeout} else anykey fi } # # install_config # -------------- # # install/update package configuration file # # Parameters: $1 name of package # if the first parameter is '--quiet' # all screen outputs are suppressed. # # Output: 0 - upgrade configuration # 1 - new configuration # install_config () { local _ic_modname local _ic_retval local _ic_quiet _ic_quiet=0 if [ "$1" = '--quiet' ] then _ic_quiet=1 shift fi _ic_modname=${1} _ic_retval=1 if [ -f /var/run/${_ic_modname}.install ] then # previous version found - upgrading if [ ${_ic_quiet} -eq 0 ] then echo "loading previous configuration file ..." fi /var/install/config.d/${_ic_modname}-update.sh update _ic_retval=0 elif [ ! -f /etc/config.d/${_ic_modname} ] then # new installation - parameter check if [ ${_ic_quiet} -eq 0 ] then echo "loading initial configuration file ..." fi cp /etc/default.d/${_ic_modname} /var/run/${_ic_modname}.install /var/install/config.d/${_ic_modname}-update.sh update fi rm -f /var/run/${_ic_modname}.install return ${_ic_retval} } # Generell information about the functions 'write_to_config_log', # 'compress_config_log' and 'display_config_log': # # The function 'write_to_config_log' writes new log messages to # the file ${configlog_file}.tmp. # The function 'compress_config_log' adds these messages to the # default logfile ${configlog_file} and then removes the # ${configlog_file}.tmp file. If new messages have been added # a marker file ${configlog_file}.newlines will be created. # The function 'display_config_log' displays the content of the # file ${configlog_file} if also a file ${configlog_file}.newlines # exists. # # write_to_config_log # ------------------- # # writes a message to config log # # Parameters: $1 function # --header print header message # --info print info message (default) # --warn print warning message # --error print error message # --ff followup entry, don't print label # # $2 message text, e.g. "This is a log message." # write_to_config_log() { local _w2cl_configdir local _w2cl_fup local _w2cl_label local _w2cl_opt _w2cl_label='Info:' _w2cl_fup=0 _w2cl_opt='' while [ 1 ] do case "$1" in -header|--header) _w2cl_opt='-e' _w2cl_label="\nDate: `date`\n" shift ;; -info|--info) _w2cl_label=' Info:' shift ;; -warn|--warn) _w2cl_label=' Warning:' shift ;; -error|--error) _w2cl_label=' Error:' shift ;; -ff|--ff) _w2cl_fup=1 shift ;; *) break ;; esac done if [ ${_w2cl_fup} -eq 1 ] then _w2cl_label="`echo \"${_w2cl_label}\"|tr 'a-zA-Z' ' '`" fi # check if destination directory exists if [ -n "${configlog_file}" ] then _w2cl_configdir="`dirname ${configlog_file}`/" if [ ! -d ${_w2cl_configdir} ] then # create directory mkdir -p ${_w2cl_configdir} fi { if [ "${_w2cl_opt}" = "-e" ] then # force print of date header echo ${_w2cl_opt} "${_w2cl_label} $*" else # print normal entry if [ ! -s ${configlog_file}.tmp ] then # file doesn't exist or is empty - prefix entry with date header printf "\nDate: `date`\n\n" fi echo ${_w2cl_opt} "${_w2cl_label} $*" fi } >> ${configlog_file}.tmp else echo "ERROR: Variable '\${configlog_file\}' not set!" fi } # # compress_config_log # ------------------- # # compress config log to given number of configuration logs # # Parameters: $1 maximum number of previous config logs # default: 5 # compress_config_log() { local _ccl_idxmax local _ccl_isnum local _ccl_maxnum local _ccl_sedstr local _ccl_tmpfile local _ccl_tmpnum1 local _ccl_tmpnum2 _ccl_idxmax=$1 if [ -z "${_ccl_idxmax}" ] then # set default number of entries _ccl_idxmax=5 elif [ ${_ccl_idxmax} -le 1 ] then # set default number of entries _ccl_idxmax=5 fi # # remove previous newline marker file # if [ -f ${configlog_file}.newlines ] then rm -f ${configlog_file}.newlines fi # # check if previous logfile contains valid log entries # and delete it if no entries are found. # if [ -f ${configlog_file} ] then # file exists - check number of lines after removing # '^Date'-lines and all empty lines and spaces _ccl_isnum=`grep -v "^Date" ${configlog_file} | sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g' -e '/^$/d' | wc -l` if [ ${_ccl_isnum} -eq 0 ] then # delete file if it does not contain log entries rm -f ${configlog_file} fi fi # # append new log entries if some entries exist. # if [ -f ${configlog_file}.tmp ] then # file exists - check number of lines after removing # '^Date'-lines and all empty lines and spaces _ccl_isnum=`grep -v "^Date" ${configlog_file}.tmp | sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g' -e '/^$/d' | wc -l` if [ ${_ccl_isnum} -gt 0 ] then # add newly created logfile to default logfile cat ${configlog_file}.tmp >> ${configlog_file} # create newline marker file echo "new loglines added" > ${configlog_file}.newlines fi rm ${configlog_file}.tmp fi # # reduce number of log entries to given limit # if [ -f ${configlog_file} ] then # file exists _ccl_tmpfile=${configlog_file}.$$ # get number of configuration blocks _ccl_maxnum=`grep -n "^Date" ${configlog_file} | wc -l` if [ ${_ccl_maxnum} -gt ${_ccl_idxmax} ] then # more than (_ccl_idxmax - 1) lines found, strip surplus lines _ccl_tmpnum1=`expr ${_ccl_maxnum} - ${_ccl_idxmax} + 1` _ccl_tmpnum2=`grep -n "^Date" ${configlog_file} | sed -n "${_ccl_tmpnum1}p" | cut -d: -f1` _ccl_sedstr=1\,`expr ${_ccl_tmpnum2} - 1`d { echo sed "${_ccl_sedstr}" ${configlog_file} } > ${_ccl_tmpfile} mv ${_ccl_tmpfile} ${configlog_file} fi fi } # # display_config_log # ------------------ # # display config log file if it exists # display_config_log() { local _dcl_answer local _dcl_ask_tmpfile local _dcl_color local _dcl_frame local _dcl_rc _dcl_color='' _dcl_frame='' if [ "${_EISLIB}" != 'true' ] then # load eislib if not already loaded . /var/install/include/eislib fi if $(grep -qE "^MENU=['\"]/var/install/bin/show-menu['\"]" /etc/config.d/setup) then _dcl_color='--nocolor' _dcl_frame='--noframe' fi if [ -f ${configlog_file} -a -f ${configlog_file}.newlines ] then _dcl_ask_tmpfile=$(/bin/mktemp -t XXXXXXXXXXXX) sleep 5 clrhome mecho --info "Configuration messages appeared, please check configuration" mecho /var/install/bin/ask "Continue" "yes" >${_dcl_ask_tmpfile} _dcl_rc=${?} _dcl_answer=$(cat ${_dcl_ask_tmpfile}) rm -f ${_dcl_ask_tmpfile} # if ask break, ask returned 255 if [ ${_dcl_rc} = 255 ] then _dcl_answer=no fi if [ "${_dcl_answer}" = 'yes' ] then /var/install/bin/show-doc.cui ${_dcl_color} ${_dcl_frame} --follow --title ${configlog_file} ${configlog_file} else exit 0 fi mecho fi } #============================================================================ # # print_short_header # ------------------ # # print a short file header which references to the config file # # Parameters: $1 file name # $2 program name # $3 module name # $4 program version # print_short_header() { local _psh_cname local _psh_fname local _psh_pname local _psh_pver _psh_fname=$1 _psh_pname=$2 _psh_cname=$3 _psh_pver=$4 if [ $# -eq 3 ] then # 'old' format _psh_cname=${_psh_pname} fi # program name _psh_pname=`basename ${_psh_pname}` # check version number echo ${_psh_pver} | grep -q "^v" if [ $? -ne 0 ] then _psh_pver="v${_psh_pver}" fi echo "#------------------------------------------------------------------" echo "# ${_psh_fname} file generated by ${_psh_pname} ${_psh_pver}" echo "#" echo "# Do not edit this file, edit /etc/config.d/${_psh_cname}" echo "# Creation Date: ${_jedlib_date} Time: ${_jedlib_time}" echo "#------------------------------------------------------------------" } #============================================================================ # # insert_date # ----------- # # insert date_stamp into text string. The position at which the date will be # inserted is being defined by the standard date placeholders. # e.g. %d.%m.%Y # # Parameters: $1 text string # # Output: modified text string # insert_date() { local _id_tmp_str1 local _id_tmp_str2 local _id_work_str _id_work_str="$1" for _RSTR in d m y Y H M S R c C e F I k l a A b B D g G h j n N p P r s t T u U V w W x X z Z do while [ 1 ] do echo "${_id_work_str}" | grep -E -q "%${_RSTR}[][\(\)\$\%\/ .,_0-9-]|%${_RSTR}$" if [ $? -eq 0 ] then _id_tmp_str1=`expr "${_id_work_str}" : "\(.*\)\%${_RSTR}"` _id_tmp_str2=`expr "${_id_work_str}" : ".*\%${_RSTR}\(.*\)"` _id_work_str="${_id_tmp_str1}`date +\"%${_RSTR}\"`${_id_tmp_str2}" else break fi done done echo "${_id_work_str}" } # # insert_hostname # --------------- # Insert hostname into text string. The position at which the hostname will be # inserted is being defined by %HN placeholder. # # Parameters: $1 text string # # Output: modified text string # insert_hostname() { local _ih_tmp_str1 local _ih_tmp_str2 local _ih_work_str _ih_work_str="$1" _RSTR="HN" while [ 1 ] do echo "${_ih_work_str}"|grep -q "%${_RSTR}[][\(\)\$\%\/ .,_0-9-]*" if [ $? -eq 0 ] then _ih_tmp_str1=`expr "${_ih_work_str}" : "\(.*\)\%${_RSTR}"` _ih_tmp_str2=`expr "${_ih_work_str}" : ".*\%${_RSTR}\(.*\)"` _ih_work_str="${_ih_tmp_str1}`hostname`${_ih_tmp_str2}" else break fi done echo "${_ih_work_str}" } # # trim_spaces # ----------- # Return string with no spaces # # Parameters: $1 string to format # $2 action: left, right, both [ optional, default: both] # # Output: string with no leading, no trailing or no leading and no # trailing spaces # trim_spaces () { local _ts_action local _ts_str _ts_str="$1" _ts_action="$2" case ${_ts_action} in left|l ) echo "${_ts_str}"|sed -e 's/^ *//' ;; right|r ) echo "${_ts_str}"|sed -e 's/ *$//' ;; all|a ) echo "${_ts_str}"|sed -e 's/ //g' ;; * ) # both | l echo "${_ts_str}"|sed -e 's/^ *//' -e 's/ *$//' ;; esac } # # get_accessrights # ---------------- # get file/directory ownership and access rights and return as string # # Parameters: $1 filename/directory # # Output: string which contains access rights, owner and group # in the following format: 'mask:owner:group' # e.g. '1666:tim:nogroup' # get_accessrights () { local _ga_name local _ga_oldifs local _ga_str local _ga_access local _ga_owner local _ga_group local _ga_bin2 local _ga_bin3 local _ga_bin4 local _ga_dec1 local _ga_dec2 local _ga_dec3 local _ga_dec4 local _ga_txt2 local _ga_txt3 local _ga_txt4 # mask '&' characters by adding a slash -> '\&' # this allows to process IMAP-UTF-7 encoded mail folder names _ga_name=`echo "$1" | sed 's#\([^\]\)\&#\1\\\\\&#g'` if [ -f ${_ga_name} -o -d ${_ga_name} ] then if [ -L ${_ga_name} ] then # symbolic link, get target folder _ga_name=`readlink -f ${_ga_name}` fi # read file data # dir : drwx------:5:otto:mailtest:4096:Nov:18:00:16:/home/otto/.imapmail # file: -rw-------:1:otto:mailtest:78892:Oct:15:20:11:/home/otto/.imapmail/INBOX _ga_str=`ls -ld ${_ga_name} | tr -s ' ' ':'` # change IFS _ga_oldifs=${IFS} IFS=' ' # file ownership data, owner, group _ga_access=`echo ${_ga_str} | cut -d: -f1` _ga_owner=`echo ${_ga_str} | cut -d: -f3` _ga_group=`echo ${_ga_str} | cut -d: -f4` # change IFS IFS=${_ga_oldifs} # extract text strings _ga_txt2=`echo ${_ga_access} | cut -c2-4` _ga_txt3=`echo ${_ga_access} | cut -c5-7` _ga_txt4=`echo ${_ga_access} | cut -c8-10` # convert to binary values _ga_bin2=`echo ${_ga_txt2} | tr '\-rwxsS' '011110'` _ga_bin3=`echo ${_ga_txt3} | tr '\-rwxsS' '011110'` _ga_bin4=`echo ${_ga_txt4} | tr '\-rwxtT' '011110'` # check if setuid bit has been set _ga_dec1=0 echo "${_ga_txt2}" | grep -E -q "s|S" if [ $? -eq 0 ] then _ga_dec1=`expr ${_ga_dec1} + 4` fi # check if setguid bit has been set echo "${_ga_txt3}" | grep -E -q "s|S" if [ $? -eq 0 ] then _ga_dec1=`expr ${_ga_dec1} + 2` fi # check if sticky-bit bit has been set echo "${_ga_txt4}" | grep -E -q "t|T" if [ $? -eq 0 ] then _ga_dec1=`expr ${_ga_dec1} + 1` fi # convert to decimal values _ga_dec2=`echo "ibase=2;${_ga_bin2}" | bc` _ga_dec3=`echo "ibase=2;${_ga_bin3}" | bc` _ga_dec4=`echo "ibase=2;${_ga_bin4}" | bc` # output: ownership data, owner, group echo "${_ga_dec1}${_ga_dec2}${_ga_dec3}${_ga_dec4}:${_ga_owner}:${_ga_group}" fi } # # set_accessrights # ---------------- # set file/directory ownership and access rights # # Parameters: $0 optional: -R/-Rall - recursive for access rights, owner, group # -Ra|-Raccess - recursive for access rights only # -Ro|-Rowner - recursive for owner only # -Rg|-Rgroup - recursive for group only # # $1 filename/directory # $2 string which contains access rights, owner and group # in the following format: 'mask:owner:group' # set_accessrights () { local _sa_access_option='' local _sa_owner_option='' local _sa_group_option='' local _sa_name local _sa_data local _sa_access local _sa_owner local _sa_group while [ $# -gt 0 ] do case "$1" in -R|-Rall ) # all _sa_access_option='-R' _sa_owner_option='-R' _sa_group_option='-R' shift ;; -Ra ) # access rights _sa_access_option='-R' shift ;; -Ro ) # owner _sa_owner_option='-R' shift ;; -Rg ) # group _sa_group_option='-R' shift ;; * ) break ;; esac done # mask '&' characters by adding a slash -> '\&' # this allows to process IMAP-UTF-7 encoded mail folder names _sa_name=`echo "$1" | sed 's#\([^\]\)\&#\1\\\\\&#g'` _sa_data="$2" if [ -f ${_sa_name} -o -d ${_sa_name} ] then # file ownership data, owner, group _sa_access=`echo "${_sa_data}" | cut -d: -f1` _sa_owner=`echo "${_sa_data}" | cut -d: -f2` _sa_group=`echo "${_sa_data}" | cut -d: -f3` # set access rights if [ -n "${_sa_access}" ] then chmod ${_sa_access_option} ${_sa_access} ${_sa_name} fi if [ -n "${_sa_owner}" ] then chown ${_sa_owner_option} ${_sa_owner} ${_sa_name} fi if [ -n "${_sa_group}" ] then chgrp ${_sa_group_option} ${_sa_group} ${_sa_name} fi fi } # # rand_char # --------- # return random char # # Output: string which contains a random char # # eisfair-2: bsdmainutils package need to be installed which contains the 'hexdump' # rand_char () { local _rc_chars local _rc_max local _rc_nbr local _rc_rand # array of allowed characters # first character is a placebo and will never be used _rc_max=64 _rc_chars="aabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-" _rc_rand="`hexdump -n 2 -e '/2 "%u"' /dev/urandom`" _rc_nbr=$(( ( ${_rc_rand} % ${_rc_max} ) + 1 )) echo "`expr substr "${_rc_chars}" ${_rc_nbr} 1`" } # # rand_string # ----------- # return random string # # Parameters: $1 length of string # # Output: string which contains a random string # rand_string () { local _rs_idx local _rs_randstr local _rs_strlen _rs_strlen=${1} # create random string _rs_idx=1 _rs_randstr="" while [ ${_rs_idx} -le ${_rs_strlen} ] do _rs_randstr="${_rs_randstr}`rand_char`" _rs_idx=`expr ${_rs_idx} + 1` done echo "${_rs_randstr}" } # # shorten_string # -------------- # return shorten string, e.g. "this-is-...long-text" # # Parameters: $1 input string # $2 max. length of string # $3 optional: separator string # # Output: shortend string # shorten_string () { local _ss_hlen local _ss_inlen local _ss_instr local _ss_len local _ss_outstr local _ss_seplen local _ss_sepstr local _ss_spos local _ss_width _ss_instr="${1}" _ss_width=${2} _ss_sepstr="${3}" if [ -z "${_ss_sepstr}" ] then _ss_sepstr="..." fi _ss_inlen=`expr length "${_ss_instr}"` if [ ${_ss_inlen} -gt ${_ss_width} ] then _ss_seplen=`expr length ${_ss_sepstr}` # length of separator string _ss_len=`expr ${_ss_width} - ${_ss_seplen}` # substract length of separator _ss_hlen=`expr ${_ss_len} \/ 2` # devide by 2 _ss_spos=`expr ${_ss_inlen} - ${_ss_hlen} + 1` # start position of 2. string _ss_outstr="`expr substr "${_ss_instr}" 1 ${_ss_hlen}`${_ss_sepstr}`expr substr "${_ss_instr}" ${_ss_spos} ${_ss_hlen}`" else _ss_outstr="${_ss_instr}" fi echo "${_ss_outstr}" } # # get_last_day_of_month # --------------------- # # get last day of month # # Parameters: $1 date string: yyyy-mm[-dd], if no date # is given the current date is used # # Output: date string # get_last_day_of_month() { local _ld_lastday local _ld_month local _ld_year # get the command line input(day month year) if [ $# -ne 1 ] then # use current date _ld_year=`date +'%Y'` _ld_month=`date +'%m'` else _ld_year=`echo ${1} |cut -d- -f1` _ld_month=`echo ${1}|cut -d- -f2` fi _ld_lastday=`cal ${_ld_month} ${_ld_year} | awk 'NF != 0{ last = $0 }; END{ print last }' | awk '{ print $NF }'` # print formated date date -d "${_ld_year}-${_ld_month}-${_ld_lastday}" +'%Y-%m-%d' } # get_yesterday # ------------- # # get previous day of of given date # # Parameters: $1 date string: yyyy-mm-dd, if no date # is given the current date will be used # # Output: date string # get_yesterday() { local _gy_date local _gy_day local _gy_month local _gy_prev_month local _gy_prev_year local _gy_year # get the command line input(day month year) if [ $# -ne 1 ] then # use current date _gy_year=`date +'%Y'` _gy_month=`date +'%m'` _gy_day=`date +'%d'` else _gy_year=`echo ${1} |cut -d- -f1` _gy_month=`echo ${1}|cut -d- -f2` _gy_day=`echo ${1} |cut -d- -f3` fi if [ ${_gy_day} -eq 1 ] then # get last day of previous month if [ ${_gy_month} -eq 1 ] then # last month of previous year _gy_prev_year=`expr ${_gy_year} - 1` _gy_date=`get_last_day_of_month "${_gy_prev_year}-12-01"` else # previous month _gy_prev_month=`expr ${_gy_month} - 1` _gy_date=`get_last_day_of_month "${_gy_year}-${_gy_prev_month}-01"` fi else _gy_date="${_gy_year}-${_gy_month}-`expr ${_gy_day} - 1`" fi # print formated date date -d "${_gy_date}" +'%Y-%m-%d' } # # get_tomorrow # ------------ # # get next day of of given date # # Parameters: $1 date string: yyyy-mm-dd, if no date # is given the current date will be used # # Output: date string # get_tomorrow() { local _gt_day local _gt_lastday local _gt_month local _gt_year # get the command line input(day month year) if [ $# -ne 1 ] then # use current date _gt_year=`date +'%Y'` _gt_month=`date +'%m'` _gt_day=`date +'%d'` else _gt_year=`echo ${1} |cut -d- -f1` _gt_month=`echo ${1}|cut -d- -f2` _gt_day=`echo ${1} |cut -d- -f3` fi # get last day of the month use cal command, discard blank lines, # take last field of last line, first awk command is used to get # the last useful line of the calendar cmd, second awk command is # used to get the last field of this last useful line, NF is no. # of fields, $NF is value of last field _gt_lastday=`cal ${_gt_month} ${_gt_year} | awk 'NF != 0{ last = $0 }; END{ print last }' | awk '{ print $NF }'` # if it is the last day of the month if [ ${_gt_day} -eq ${_gt_lastday} ] then # make the day as 01 _gt_day=01 # if it is the last month of the year if [ ${_gt_month} -eq 12 ] then # make the month as 01 _gt_month=01 # increment the year by one _gt_year=`expr ${_gt_year} + 1` else # increment the month by one _gt_month=`expr ${_gt_month} + 1` fi else # increment the day by one _gt_day=`expr ${_gt_day} + 1` fi # print formated date date -d "${_gt_year}-${_gt_month}-${_gt_day}" +'%Y-%m-%d' } # get_diff_days # ------------- # # get number of days between two dates # # Switch: $1 optional: --with-sign - output value with leading +/- sign # # Parameters: $1 date string: yyyy-mm-dd, if no date # is given -1 will be returned # $2 date string: yyyy-mm-dd, if no date # is given the current date will be used # # Output: date string # get_diff_days () { local _gdd_with_sign=0 if [ "$1" = '--with-sign' ] then _gdd_with_sign=1 shift fi local _gdd_date_val1 local _gdd_date_val2 local _gdd_diff_days='' local _gdd_diff_secs # get the command line input if [ -n "${1}" ] then if [ -n "`echo "${1}" | sed 's/^[0-9 :-]*//g'`" ] then # date includes timezone, like e.g. '2020-07-10 23:13 CEST' _gdd_date_val1=`date +'%s' -d "${1}"` else # append default time zone UTC _gdd_date_val1=`date +'%s' -d "${1} 00:00:00 UTC"` fi if [ -z "${2}" ] then _gdd_date_val2=`date +'%s' -d "00:00:00 UTC"` else if [ -n "`echo "${2}" | sed 's/^[0-9 :-]*//g'`" ] then # date includes timezone, like e.g. '2020-07-10 23:13 CEST' _gdd_date_val2=`date +'%s' -d "${2}"` else # append default time zone UTC _gdd_date_val2=`date +'%s' -d "${2} 00:00:00 UTC"` fi fi if [ ${_gdd_date_val1} -eq ${_gdd_date_val2} ] then # same day _gdd_diff_days=0 else # dates differ _gdd_diff_secs=`expr ${_gdd_date_val1} - ${_gdd_date_val2}` # devide by number of seconds per day _gdd_diff_days=`expr ${_gdd_diff_secs} \/ 86400` fi fi if [ ${_gdd_with_sign} -eq 1 ] then # prepend leading + sign echo "${_gdd_diff_days}" | sed 's/^\([0-9]\)/+\1/' else # strip-off leading +/- sign echo "${_gdd_diff_days}" | sed 's/^[+-]//' fi } # get_diff_dates # -------------- # # get number of years, month, days, hours, minutes and seconds # between two dates # # Parameters: $1 date string: yyyy-mm-dd, if no date # is given -1 will be returned # $2 date string: yyyy-mm-dd, if no date # is given the current date will be used # # Output: date diff string # get_diff_dates () { local _gdd_date_val1 local _gdd_date_val2 local _gdd_diff_days local _gdd_diff_secs local _gdd_days local _gdd_operator local _gdd_temp local _gdd_years if [ $# -ge 1 ] then _gdd_date_val1=`date +'%s' -ud "${1}"` if [ $# -ge 2 ] then _gdd_date_val2=`date +'%s' -ud "${2}"` else # use current date _gdd_date_val2=`date +'%s'` fi if [ ${_gdd_date_val1} -gt ${_gdd_date_val2} ] then # date1 greater than date2 _gdd_diff_secs=`expr ${_gdd_date_val1} - ${_gdd_date_val2}` elif [ ${_gdd_date_val2} -gt ${_gdd_date_val1} ] then # date2 greater than date1 _gdd_diff_secs=`expr ${_gdd_date_val2} - ${_gdd_date_val1}` else # date2 equal date1 _gdd_diff_secs=0 fi if [ ${_gdd_diff_secs} -ne 0 ] then _gdd_diff_days='' # years _gdd_temp=`date -d@${_gdd_diff_secs} +'%Y'` _gdd_years=`expr ${_gdd_temp} - 1970` if [ ${_gdd_years} -gt 0 ] then _gdd_diff_days="${_gdd_years} years " fi # months _gdd_temp=`date -d@${_gdd_diff_secs} +'%m' | sed 's/^0//'` _gdd_months=`expr ${_gdd_temp} - 1` _gdd_operator='ge' if [ -z "${_gdd_diff_days}" ] then _gdd_operator='gt' fi if [ ${_gdd_months} -${_gdd_operator} 0 ] then if [ ${_gdd_months} -eq 1 ] then _gdd_diff_days="${_gdd_diff_days}${_gdd_months} month " else _gdd_diff_days="${_gdd_diff_days}${_gdd_months} months " fi fi # days _gdd_temp=`date -d@${_gdd_diff_secs} +'%d' | sed 's/^0//'` _gdd_days=`expr ${_gdd_temp} - 1` _gdd_operator='ge' if [ -z "${_gdd_diff_days}" ] then _gdd_operator='gt' fi if [ ${_gdd_days} -${_gdd_operator} 0 ] then if [ ${_gdd_days} -eq 1 ] then _gdd_diff_days="${_gdd_diff_days}${_gdd_days} day " else _gdd_diff_days="${_gdd_diff_days}${_gdd_days} days " fi fi # hours _gdd_temp=`date -d@${_gdd_diff_secs} +'%H' | sed 's/^0//'` _gdd_hours=`expr ${_gdd_temp} - 1` _gdd_operator='ge' if [ -z "${_gdd_diff_days}" ] then _gdd_operator='gt' fi if [ ${_gdd_hours} -${_gdd_operator} 0 ] then if [ ${_gdd_hours} -eq 1 ] then _gdd_diff_days="${_gdd_diff_days}${_gdd_hours} hour " else _gdd_diff_days="${_gdd_diff_days}${_gdd_hours} hours " fi fi # minute _gdd_temp=`date -d@${_gdd_diff_secs} +'%M' | sed 's/^0//'` _gdd_minutes=`expr ${_gdd_temp} - 1` _gdd_operator='ge' if [ -z "${_gdd_diff_days}" ] then _gdd_operator='gt' fi if [ ${_gdd_minutes} -${_gdd_operator} 0 ] then if [ ${_gdd_minutes} -eq 1 ] then _gdd_diff_days="${_gdd_diff_days}${_gdd_minutes} minute " else _gdd_diff_days="${_gdd_diff_days}${_gdd_minutes} minutes " fi fi # seconds _gdd_seconds=`date -d@${_gdd_diff_secs} +'%S' | sed 's/^0//'` _gdd_operator='ge' if [ -z "${_gdd_diff_days}" ] then _gdd_operator='gt' fi if [ ${_gdd_seconds} -${_gdd_operator} 0 ] then if [ ${_gdd_seconds} -eq 1 ] then _gdd_diff_days="${_gdd_diff_days}${_gdd_seconds} second" else _gdd_diff_days="${_gdd_diff_days}${_gdd_seconds} seconds" fi else _gdd_diff_days="both dates are the same" fi else _gdd_diff_days="both dates are the same" fi else # invalid number of parameters given _gdd_diff_days=-1 fi echo "${_gdd_diff_days}" } # sec_to_formated_time # -------------------- # # convert seconds to a formated time "[HH:]MM:SS" # # Parameters: $1 seconds # $2 'full-length' or empty '' # # Output: formated time "[HH:]MM:SS" # sec_to_formated_time () { local _stft_length local _stft_ret local _stft_value _stft_value=`echo "${1}" | sed 's/[^0-9]*//g'` _stft_length=`echo "${2}" | tr '[:upper:]' '[:lower:]'` _stft_ret='' if [ -n "${_stft_value}" ] then if [ ${_stft_value} -lt 3600 -a "${_stft_length}" != 'full-length' ] then # MM:SS _stft_ret=`date --date="@${_stft_value}" -u +'%M:%S'` elif [ ${_stft_value} -lt 86400 ] then # HH:MM:SS _stft_ret=`date --date="@${_stft_value}" -u +'%H:%M:%S'` else _stft_ret="value to big" fi fi echo "${_stft_ret}" } # formated_time_to_sec # -------------------- # # convert formated time "[HH:]MM:SS" to seconds # # Parameters: $1 formated time "[HH:]MM:SS" # # Output: seconds # formated_time_to_sec () { local _ftts_count local _ftts_result local _ftts_time local _ftts_hour local _ftts_min local _ftts_sec _ftts_time="${1}" _ftts_result='' if [ -n "${_ftts_time}" ] then _ftts_count=`echo "${_ftts_time}" | awk -F: '{print NF}'` case ${_ftts_count} in 3 ) _ftts_hour=`echo "${_ftts_time}" | cut -d: -f1` _ftts_min=`echo "${_ftts_time}" | cut -d: -f2` _ftts_sec=`echo "${_ftts_time}" | cut -d: -f3` ;; 2 ) _ftts_hour=0 _ftts_min=`echo "${_ftts_time}" | cut -d: -f1` _ftts_sec=`echo "${_ftts_time}" | cut -d: -f2` ;; 1 ) _ftts_hour=0 _ftts_min=0 _ftts_sec=`echo "${_ftts_time}" | cut -d: -f1` ;; * ) echo "error in function 'formated_time_to_sec', invalid time format!" ;; esac _ftts_result=`echo "(${_ftts_hour} * 60 * 60) + (${_ftts_min} * 60) + ${_ftts_sec}" | bc` fi echo "${_ftts_result}" } # unit_to_numeric # --------------- # # convert integer value including unit to a pure integer value # # Parameters: $1 value incl. unit (k)ilo, (m)ega, (g)iga, (t)erabyte # # Output: pure integer value # unit_to_numeric () { local _u2n_ret local _u2n_unit local _u2n_value _u2n_value=`echo ${1} | sed -e 's/[kKmMgGtT]//g' -e 's/,/\./g'` _u2n_unit=`echo ${1} | sed 's/[0-9.,]//g'` case ${_u2n_unit} in k|K) # kilobyte given - *1024 # 1. calculate, 2. round, 3. take integer _u2n_ret=`bc <<< "${_u2n_value} * 1024 + 0.5" | sed 's/[.,].*$//'` ;; m|M) # megabyte given - *1024*1024 # 1. calculate, 2. round, 3. take integer _u2n_ret=`bc <<< "${_u2n_value} * 1048576 + 0.5" | sed 's/[.,].*$//'` ;; g|G) # gigabyte given - *1024*1024*1024 # 1. calculate, 2. round, 3. take integer _u2n_ret=`bc <<< "${_u2n_value} * 1073741824 + 0.5" | sed 's/[.,].*$//'` ;; t|T) # terabyte given - *1024*1024*1024*1024 # 1. calculate, 2. round, 3. take integer _u2n_ret=`bc <<< "${_u2n_value} * 1099511627776 + 0.5" | sed 's/[.,].*$//'` ;; *) # return original value _u2n_ret=${1} ;; esac echo ${_u2n_ret} } # numeric_to_unit # --------------- # # convert a pure integer value to value including unit (divisor: 1024) # # Parameters: $1 pure integer value # $2 optional, unit string, default: '. k M G T P' # $3 optional, number of decimal figures # # Output: value incl. unit (k)ilo, (M)ega, (G)iga, (T)era, (P)eta, # by default rounded with 3 decimals # numeric_to_unit () { local _n2u_curr_unit='' local _n2u_curr_value='' local _n2u_default_units=". k M G T P" local _n2u_idx local _n2u_maxidx local _n2u_mode local _n2u_value=${1} local _n2u_unit=${2} local _n2u_decimals=${3} local _n2u_zero_string # set unit automatically if [ -z "${_n2u_unit}" ] then _n2u_unit='a' fi # set default number of decimals if [ -z "${_n2u_decimals}" ] then _n2u_decimals='3' fi if [ -n "${_n2u_value}" ] then if [ "${_n2u_unit}" = 'a' ] then # automatic unit mode, set to max value _n2u_mode='==AUTO-MODE==' _n2u_idx=1 _n2u_maxidx=`echo ${_n2u_default_units} | wc -w` while [ ${_n2u_idx} -le ${_n2u_maxidx} ] do if [ -z "${_n2u_curr_value}" ] then _n2u_curr_value=${_n2u_value} fi _n2u_int_value=`echo "${_n2u_curr_value}" | sed 's/^\(.*\)\..*$/\1/'` if [ ${_n2u_int_value} -ge 1024 ] then # devide value _n2u_curr_value=`echo "${_n2u_curr_value}/1024" | bc -l` _n2u_int_value=`echo "${_n2u_curr_value}" | sed 's/^\(.*\)\..*$/\1/'` else break fi # get current unit _n2u_idx=`expr ${_n2u_idx} + 1` _n2u_curr_unit=`echo "${_n2u_default_units}" | cut -d' ' -f${_n2u_idx}` done else _n2u_mode='==MANUAL-MODE==' _n2u_idx=1 _n2u_maxidx=1 _n2u_unit_found=0 for STR in ${_n2u_default_units} do if [ "${STR}" = "${_n2u_unit}" ] then _n2u_unit_found=1 break fi _n2u_maxidx=`expr ${_n2u_maxidx} + 1` done if [ ${_n2u_unit_found} -eq 0 ] then _n2u_maxidx=1 fi while [ ${_n2u_idx} -le ${_n2u_maxidx} ] do if [ -z "${_n2u_curr_value}" ] then _n2u_curr_value=${_n2u_value} fi # devide value _n2u_curr_value=`echo "${_n2u_curr_value}/1024" | bc -l` _n2u_int_value=`echo "${_n2u_curr_value}" | sed 's/^\(.*\)\..*$/\1/'` # get current unit _n2u_idx=`expr ${_n2u_idx} + 1` _n2u_curr_unit=`echo "${_n2u_default_units}" | cut -d' ' -f${_n2u_idx}` if [ "${_n2u_unit}" = "${_n2u_curr_unit}" ] then break fi done fi else # error _n2u_curr_value='empty' fi if [ "${_n2u_curr_unit}" = '.' ] then _n2u_unit='' fi # check decimal value echo "${_n2u_curr_value}" | grep -q '\.' if [ $? -eq 0 ] then # decimal separator found, get decimal value _n2u_int_decimals=`echo "${_n2u_curr_value}" | sed 's/^.*\.\(.*\)$/\1/'` if [ -n "${_n2u_int_decimals}" ] then # decimal value not empty, go on... if [ ${_n2u_decimals} -gt 0 ] then # by default a decimal value should be printed, go on... if [ `echo "${_n2u_curr_value} > 0" | bc -l` -eq 1 ] then # decimal value is greater than 0, round it _n2u_zero_string=`printf %${_n2u_decimals}s | tr ' ' '0'` _n2u_curr_value=`echo "${_n2u_curr_value}+.${_n2u_zero_string}5" | bc -l` else # do not print '0' decimal value _n2u_decimals=0 fi fi else # do not print '0' decimal value _n2u_decimals=0 fi else # do not print '0' decimal value _n2u_decimals=0 fi # output formatted value printf "%.${_n2u_decimals}f ${_n2u_curr_unit}\n" ${_n2u_curr_value} } # abs_path # -------- # # return absolute path to a file # # Parameters: $1 path of file # # Output: absolute path of file # abs_path () { cd "$(dirname "$1")" printf "$(pwd)/$(basename "$1")\n" cd "${OLDPWD}" } # delay_script_exec # ----------------- # # Parameters: $1 name/regexp to identify current process # e.g. '${pgmname}.*--single' # $2 delay of next check in seconds, def: 10s # delay_script_exec () { local _dse_delay local _dse_first_pid local _dse_pid_names local _dse_proc_name _dse_proc_name="$1" _dse_delay="$2" if [ -z "${_dse_delay}" ] then _dse_delay=10 fi if [ -n "${_dse_proc_name}" ] then _dse_first_pid='' until [ "$$" = "${_dse_first_pid}" ] do # check if current process is the first one on the list. # use the ps command with the '-ww' switch to make sure # that really all parameters # are shown, independently # of the screen width. _dse_pid_names=`ps -efww | grep -v "grep " | grep -E "${_dse_proc_name}"` _dse_first_pid=`echo "${_dse_pid_names}" | awk -F" " '{print $2}' | head -1` if [ "$$" != "${_dse_first_pid}" ] then # delay script execution sleep ${_dse_delay} fi done else # error echo "error: delay_script_exec needs a process name!" fi } # format_version # -------------- # # Return a formatted version number # # Parameters: $1 count of version fields, or empty # $2 version number, e.g. 1.2.3 # # Output: reformated version number, optionally # enhanced to a given number of fields # format_version () { local _fv_fields local _fv_idx local _fv_max_idx local _fv_new_version local _fv_value local _fv_version _fv_fields="$1" _fv_version="$(echo "$2" | tr -d ' ')" if [ -n "${_fv_fields}" ] then # number of version fields _fv_max_idx="${_fv_fields}" else # count number of version fields, e.g. 1.2.3 -> 3 fields _fv_max_idx=$(echo "${_fv_version}" | awk -F"." '{print NF}') fi if [ ${_fv_max_idx} -eq 2 ] then # make sure that at least one field separator (dot) exists _fv_version="$(echo "${_fv_version}." | sed 's/\.\.*$/\./')" fi _fv_idx=1 _fv_new_version='' while [ ${_fv_idx} -le ${_fv_max_idx} ] do # loop through each version field, reduce number of zeros in zero-only string to one _fv_value=$(echo "${_fv_version}" | cut -d. -f${_fv_idx} | sed -e 's/^00*/0/' -e 's/0\([1-9]\)/\1/') if [ -z "${_fv_value}" ] then # empty field, set to zero if [ -z "${_fv_new_version}" ] then # first figure _fv_new_version="0" else # separate figure by dot _fv_new_version="${_fv_new_version}.0" fi else # version number given if [ -z "${_fv_new_version}" ] then # first figure _fv_new_version="${_fv_value}" else # separate figure by dot _fv_new_version="${_fv_new_version}.${_fv_value}" fi fi _fv_idx=`expr ${_fv_idx} + 1` done echo "${_fv_new_version}" } # compare_version # --------------- # # Return the result of a version number comparison # # Inspired by: https://stackoverflow.com/questions/4023830/how-to- # compare-two-strings-in-dot-separated-version-format-in-bash # # Switch: [--text] - output result in text form # # Parameters: $1 - first version number # $2 - second version number # # Output: 0 / installed - version1 = version2 # 1 / old - version1 < version2 # 2 / new - version1 > version2 # compare_version () { local _cv_count1 local _cv_count2 local _cv_max local _cv_pos local _cv_retval local _cv_rettext local _cv_text local _cv_version1 local _cv_version2 _cv_text=0 if [ "$1" = '--text' ] then _cv_text=1 shift fi # count number of fields _cv_count1=$(echo "$1" | awk -F"." '{print NF}') _cv_count2=$(echo "$2" | awk -F"." '{print NF}') if [ ${_cv_count1} -gt ${_cv_count2} ] then _cv_max=${_cv_count1} else _cv_max=${_cv_count2} fi # format version number _cv_version1=`format_version "${_cv_max}" "$1"` _cv_version2=`format_version "${_cv_max}" "$2"` if [ "${_cv_version1}" = "${_cv_version2}" ] then # version1 = version2 # printf "${_cv_version1}\t${_cv_version2}\t=\n" _cv_retval=0 _cv_rettext='installed' else # check if version1 is found in first line of sorted output _cv_pos=`printf "${_cv_version1}\n${_cv_version2}\n" | sort -V | grep -n "^${_cv_version1}$" | cut -d: -f1` if [ ${_cv_pos} -eq 1 ] then # version1 < version2 # printf "${_cv_version1}\t${_cv_version2}\t<\n" _cv_retval=1 _cv_rettext='old' else # version1 > version2 # printf "${_cv_version1}\t${_cv_version2}\t>\n" _cv_retval=2 _cv_rettext='new' fi fi if [ ${_cv_text} -eq 1 ] then echo "${_cv_rettext}" else return ${_cv_retval} fi } # imaputf7_encode # --------------- # # Return IMAP-UTF7 encoded string from normal string # # Parameters: $1 normal string # # Output: IMAP-UTF7 encoded string # # Example: 'Müller&Meier-sind-böse' -> 'M&APw-ller&-Meier-sind-b&APY-se' # imaputf7_encode() { local _iue_src_str="$1" local _iue_separator='/' local _iue_max local _iue_idx local _iue_char='' local _iue_hex='' local _iue_dest_str='' local _iue_tmp_str='' local _iue_iconv='/usr/bin/iconv' if [ ! -x "${_iue_iconv}" ] then echo "ERROR: function requires the '${_iue_iconv}' program which couldn't be found!" exit 1 else if [ -n "${dovecot_separator}" ] then _iue_separator="${dovecot_separator}" fi _iue_max=`expr length "${_iue_src_str}"` _iue_idx=1 while [ ${_iue_idx} -le ${_iue_max} ] do # get character and hex value _iue_char=`echo "${_iue_src_str}" | cut -c ${_iue_idx}` _iue_hex=`echo "${_iue_char}" | tr -d '\n' | xxd -i | sed -e 's/ *0x//g' -e 's/,/ /g'` # DEBUG="IDX:${_iue_idx} CHAR:${_iue_char} HEX:${_iue_hex}" case ${_iue_hex} in 2[0-5]|2[7-9a-f]|[3-7][0-9a-e] ) # append the following characters (0x20-0x25 and 0x27-0x7e): # 0-9 A-Z a-z ' ' ! " # $ % ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ ` { | } ~ if [ -n "${_iue_tmp_str}" ] then # append encoded tmp string and character _iue_dest_str="${_iue_dest_str}`echo "${_iue_tmp_str}${_iue_char}" | \ iconv -f utf-8 -t utf-7 | tr '\+' '\&'`" _iue_tmp_str='' else # append character _iue_dest_str="${_iue_dest_str}${_iue_char}" fi ;; 26 ) # append '&' (ampersand) (0x26): _iue_dest_str="${_iue_dest_str}&-" ;; 5f ) # append '_' (underscore) (0x5f): _iue_dest_str="${_iue_dest_str}_" ;; 0a ) # skip new line character (0x0a): ;; * ) # append to tmp string _iue_tmp_str="${_iue_tmp_str}${_iue_char}" ;; esac _iue_idx=`expr ${_iue_idx} + 1` done if [ -n "${_iue_tmp_str}" ] then # append encoded tmp string _iue_dest_str="${_iue_dest_str}`echo "${_iue_tmp_str}" | iconv -f utf-8 -t utf-7 | tr '\+' '\&'`-" _iue_tmp_str='' fi # check if source string already contains encoded dots echo "${_iue_src_str}" | grep -q '\\2e' if [ $? -eq 0 ] then # 1. make sure that '\2e' entries are output as '\\2e' # 2. replace '/' (slash) by '.' (dot) _iue_dest_str="`echo "${_iue_dest_str}" | sed -e 's|^\([^\\]*\)\\\2e|\1\\\\\\\\2e|g' -e "s#${_iue_separator}#.#g"`" else echo "${_iue_src_str}" | grep -q '/' if [ $? -eq 0 ] then # 1. replace '.' (dot) by '\2e' # 2. replace '/' (slash) by '.' (dot) _iue_dest_str="`echo "${_iue_dest_str}" | sed -e 's|\.|\\\\2e|g' -e "s#${_iue_separator}#.#g"`" fi fi # output result echo "${_iue_dest_str}" fi } # imaputf7_decode # --------------- # # Return normal string from IMAP-UTF7 encoded string # # Parameters: $1 IMAP-UTF7 encoded string # # Output: normal string # # Example: 'M&APw-ller&-Meier-sind-b&APY-se' -> 'Müller&Meier-sind-böse' # imaputf7_decode() { local _iud_src_str="$1" local _iud_separator='/' local _iud_dest_str='' local _iud_left_str='' local _iud_exit=0 local _iud_iconv='/usr/bin/iconv' if [ ! -x "${_iud_iconv}" ] then echo "ERROR: function requires the '${_iud_iconv}' program which couldn't be found!" exit 1 else if [ -n "${dovecot_separator}" ] then _iud_separator="${dovecot_separator}" fi # 'Ablage.Nachbarn.Heinz\\2eMeier' # 1. replace '.' (dot) by '/' (slash) # 2. replace '\\\\' by '&&' (placeholder) # 3. replace '&&2e' (placeholder) by '.' (dot) # 4. replace all '&[^-]' matches by '+' (plus) - don't replace '&-'! _iud_src_str=`echo "${_iud_src_str}" | sed -e "s#\.#${_iud_separator}#g" | tr '\\\\' '&' | sed -e 's/&&2e/\./g' -e 's/\&\([^-]\)/\+\1/g'` while [ ${_iud_exit} -eq 0 ] do # check if string contains '&-' echo "${_iud_src_str}" | grep -q '&-' if [ $? -eq 0 ] then # match found # 5. cut of left part of string and convert it from utf-7 to utf-8 # 6. preserve right part of string for next loop _iud_left_str=`echo "${_iud_src_str}" | sed 's/^\(.*\)\&\-.*$/\1/' | ${_iud_iconv} -f utf-7 -t utf-8` _iud_src_str=`echo "${_iud_src_str}" | sed 's/^.*\&\-\(.*\)$/\1/'` # 7. append '&' to left part of string # 8. append the result to the destination string _iud_dest_str="${_iud_dest_str}${_iud_left_str}&" else # no match found # 9. convert remaining string from utf-7 to utf-8 # 10. append the result to the destination string _iud_dest_str="${_iud_dest_str}`echo "${_iud_src_str}" | ${_iud_iconv} -f utf-7 -t utf-8`" _iud_exit=1 fi done # output result echo "${_iud_dest_str}" fi } # mime_encode # ----------- # # Return a MIME encoded string from a normal text string # # Switches: $1 Optional: '--b64' - force Base64 encoded string # '--qp' - force Quoted Printable encoded # string # ! Without one of these switches the encoder will decide # ! on its own, which of the encodings will be used. # # Parameters: $1 text string to be encoded # mime_encode() { local _men_encoding='MIME-Header' local _men_perl='/usr/bin/perl' if [ "$1" = '--b64' -o "$1" = '-b64' ] then _men_encoding='MIME-B' shift elif [ "$1" = '--qp' -o "$1" = '-qp' ] then _men_encoding='MIME-Q' shift fi if [ ! -x "${_men_perl}" ] then echo "ERROR: function requires the '${_men_perl}' program which couldn't be found!" exit 1 else # encode string echo "$1" | perl -CS -MEncode -ne "print encode(\"${_men_encoding}\", \$_)" fi } # mime_decode # ----------- # # Return a normal text string from a MIME encoded input # # Parameters: $1 MIME encoded string to be decoded # mime_decode() { local _mde_perl='/usr/bin/perl' if [ ! -x "${_mde_perl}" ] then echo "ERROR: function requires the '${_mde_perl}' program which couldn't be found!" exit 1 else # decode string and concatenate multiple output lines echo "$1" | perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | sed -e :a -e '/$/N; s/\n //; ta' fi } #============================================================================ # # is_root # ------- # # check if root equivalent user # # Parameters: $1 username # # Output: 0 - yes, root user # 1 - no # is_root () { local _ir_ret local _ir_user_name local _ir_user_uid _ir_user_name="$1" _ir_ret=1 # read uid _ir_user_uid=`getent passwd ${_ir_user_name} | cut -d: -f3 | tail -n1` if [ ${_ir_user_uid} -eq 0 ] then # equivalent root user _ir_ret=0 fi return ${_ir_ret} } # # is_numeric # ---------- # # check if numeric value # # Parameters: $1 value # # Output: 0 - yes, numeric value # 1 - no, no numeric value # is_numeric () { if [ -z "$1" ] then # empty string return 1 else echo "$1"|grep -q '^[0-9]*$' fi } # # is_date # ------- # # check if date value # # Parameters: $1 - date string [yyyy-mm-dd] # # Output: 0 - ok # bit-1 - invalid year # bit-2 - invalid month # bit-3 - invalid day # is_date () { local _id_dd local _id_mm local _id_yy local _id_dd_ok local _id_mm_ok local _id_yy_ok local _id_ret _id_yy=`echo ${1} | cut -d- -f1` _id_mm=`echo ${1} | cut -d- -f2` _id_dd=`echo ${1} | cut -d- -f3` # check year _id_yy_ok=1 if [ -n "${_id_yy}" ] then if is_numeric ${_id_yy} then if [ ${_id_yy} -ge 2007 -a ${_id_yy} -le 2200 ] then _id_yy_ok=0 fi fi fi # check month _id_mm_ok=2 if [ -n "${_id_mm}" ] then if is_numeric ${_id_mm} then if [ ${_id_mm} -ge 1 -a ${_id_mm} -le 12 ] then _id_mm_ok=0 fi fi fi # check day _id_dd_ok=4 if [ -n "${_id_dd}" ] then if is_numeric ${_id_dd} then if [ ${_id_dd} -ge 1 -a ${_id_dd} -le 31 ] then # check if day is not a leap-day, e.g. 2018-02-29 date --date "${1}" >/dev/null 2>&1 if [ $? -eq 0 ] then _id_dd_ok=0 fi fi fi fi _id_ret=`expr ${_id_yy_ok} + ${_id_mm_ok} + ${_id_dd_ok}` return ${_id_ret} } # # is_time # ------- # # check if time value # # Parameters: $1 - time string [HH:MM:SS] # # Output: 0 - ok # bit-1 - invalid hour # bit-2 - invalid minute # bit-3 - invalid second # is_time () { local _it_hh local _it_mm local _it_ss local _it_hh_ok local _it_mm_ok local _it_ss_ok local _it_ret _it_hh=`echo ${1} | cut -d: -f1` _it_mm=`echo ${1} | cut -d: -f2` _it_ss=`echo ${1} | cut -d: -f3` # check hours _it_hh_ok=1 if [ -n "${_it_hh}" ] then if is_numeric ${_it_hh} then if [ ${_it_hh} -ge 0 -a ${_it_hh} -le 24 ] then _it_hh_ok=0 fi fi fi # check minutes _it_mm_ok=1 if [ -n "${_it_mm}" ] then if is_numeric ${_it_mm} then if [ ${_it_mm} -ge 0 -a ${_it_mm} -le 59 ] then _it_mm_ok=0 fi fi fi # check seconds _it_ss_ok=1 if [ -n "${_it_ss}" ] then if is_numeric ${_it_ss} then if [ ${_it_ss} -ge 0 -a ${_it_ss} -le 60 ] then _it_ss_ok=0 fi fi fi _it_ret=`expr ${_it_hh_ok} + ${_it_mm_ok} + ${_it_ss_ok}` return ${_it_ret} } # # called_from_install # ------------------- # # check if script has been called during the installation process # # Parameters: $1/$2 --package <package name> # # Output: 0 - called during install process # 1 - not called during install process # called_from_install () { local _cfi_debug_output local _cfi_package local _cfi_parent_cmd local _cfi_ret _cfi_exit=0 while [ ${_cfi_exit} -eq 0 ] do case $1 in *-pack|*-package ) _cfi_package="$2" shift; shift ;; * ) _cfi_exit=1 ;; esac done _cfi_ret=1 _cfi_debug_output=/root/.eisfair-debug-output # get calling script/program # -------------------------- # # during an installation: # /tmp/install.sh : /bin/bash /usr/share/eisman/eisman_install.sh --auto --url=file:///... # /tmp/preinstall.sh : /bin/bash /usr/share/eisman/eisman_install.sh --unstable ... # : /usr/bin/gawk -v packages= ... -v action=install -v url=file:///... # /var/install/config.d/<package>-update.sh: sh /tmp/install.sh file:///... # /var/install/config.d/<package>.sh : sh /tmp/install.sh file:///... # /var/install/deinstall/<package> : /bin/bash /usr/share/eisman/eisman_uninstall.sh --update ... # # from the command line: # /var/install/config.d/<package>.sh : bash -rcfile .bashrc # # from the ECE: # /var/install/config.d/<package>.sh : /bin/sh /var/install/bin/edit -apply /etc/config.d/<package> _cfi_parent_cmd="$(ps -o args= $PPID)" echo "${_cfi_parent_cmd}" | grep -q -E "/install.sh|/eisman_install.sh|/eisman_uninstall.sh *--update|/usr/bin/gawk -v packages=" _cfi_ret=$? if [ -f ${_cfi_debug_output} -a -n "${_cfi_package}" ] then # check if an override has been set grep -q "^[[:space:]]*${_cfi_package}[[:space:]]*$" ${_cfi_debug_output} if [ $? -eq 0 ] then _cfi_ret=2 fi fi return ${_cfi_ret} } # # host_exists # ----------- # # Parameters: $1 - url # # Output: 0 - host exists # 1 - host doesn't exist # host_exists () { local _he_ipaddr local _he_retval local _he_srvname local _he_urlstr _he_retval=1 _he_urlstr="${1}" # check if dnsip program exists type dnsip >/dev/null 2>/dev/null if [ $? -eq 0 ] then _he_srvname="`echo "${_he_urlstr}" | sed -e 's#^.*[http|ftp].*://##' -e 's#/.*$##'`" _he_ipaddr=`dnsip ${_he_srvname}` if [ -n "${_he_ipaddr}" ] then # host found _he_retval=0 fi fi return ${_he_retval} } # # get_ipaddr_port # --------------- # # Parameters: $1 - requested data: --type, --addr (default), --port, --all # $2 - ip address with/without port # $3 - if --port or --all is used, and optional default porti # can be defined # # Output: result based on data requested using $1 # if '--all' is used, the different options are separated using # a pipe character: <ip-version (4|6)>|<ip-address>|<ip-port> # get_ipaddr_port () { local _gip_reqtype=`echo "$1" | tr [:upper:] [:lower:]` local _gip_ipaddrport=`echo "$2" | sed 's/ *//g'` local _gip_def_ipport=`echo "$3" | sed 's/^\([0-9]*\).*$/\1/'` local _gip_res_iptype=4 local _gip_res_ipaddr='' local _gip_res_ipport='' local _gip_ccount=0 local _gip_bcount=0 if [ -n "${_gip_ipaddrport}" ] then _gip_ccount=`echo "${_gip_ipaddrport}" | awk -F':' '{print NF-1}'` _gip_bcount=`echo "${_gip_ipaddrport}" | awk -F"]:" '{print NF-1}'` case ${_gip_ccount} in 0 ) # IPv4 - ip address / host name without port _gip_res_ipaddr="${_gip_ipaddrport}" if [ -n "${_gip_def_ipport}" ] then _gip_res_ipport="${_gip_def_ipport}" fi ;; 1 ) # IPv4 - ip address / host name with port _gip_res_ipaddr=`echo "${_gip_ipaddrport}" | cut -d':' -f1` _gip_res_ipport=`echo "${_gip_ipaddrport}" | cut -d':' -f2` ;; * ) # IPv6 - ip address _gip_res_iptype=6 _gip_res_ipaddr=`echo "${_gip_ipaddrport}" | sed 's/^\[*\([a-f0-9:]*\)\]*\]*.*$/\1/'` if [ ${_gip_bcount} -eq 0 ] then # ip address without port if [ -n "${_gip_def_ipport}" ] then _gip_res_ipport="${_gip_def_ipport}" fi else # ip address with port _gip_res_ipport=`echo "${_gip_ipaddrport}" | sed 's/^\[*[a-f0-9:]*\]*\]:\([0-9]*\)$/\1/'` fi ;; esac fi case ${_gip_reqtype} in -*all ) echo "${_gip_res_iptype}|${_gip_res_ipaddr}|${_gip_res_ipport}" ;; -*type ) echo "${_gip_res_iptype}" ;; -*port ) echo "${_gip_res_ipport}" ;; -*addr|* ) # default: ip address echo "${_gip_res_ipaddr}" ;; esac } fi