#!/bin/sh
################################################################################
# _ #
# _ __ (_)_____ ___ ____ _____ #
# | | /| / // // ___// _ \ / __ \ / ___/ #
# | |/ |/ // // /__ / __// / / /(__ ) #
# |__/|__//_/ \___/ \___//_/ /_//____/ #
# #
# WAN IP Change Email Notification Script #
# #
################################################################################
# Thanks to all who contribute(d) at SNBforums, pieces of your code are here ;)
# written by maverickcdn
# github.com/maverickcdn/wicens
# SNBforums thread https://www.snbforums.com/threads/wicens-wan-ip-change-email-notification-script.69294/
# found in amtm thanks to @thelonelycoder
# shellcheck disable=SC2039,SC2183,SC2104,SC1090,SC2154,SC2034
# hex expr menuprintf continuefunc constantsource unassvar unusedvar
[ "$1" = 'debug' ] && shift && set -x
export PATH="/sbin:/bin:/usr/sbin:/usr/bin:$PATH"
start_time="$(awk '{print $1}' < /proc/uptime)" # for calc menu load time in ms
printf '\033[?7l' # disable terminal word wrap
# START ###############################################################################################################
script_version='4.13'
script_ver_date='Dec 4 2025'
current_core_config='4.3' # version of core config (F_default_update_create)
current_user_config='4.1' # version of user config (F_default_user_create)
script_name="$(basename "$0")"
script_name_full="/jffs/scripts/$script_name"
script_dir='/jffs/addons/wicens'
script_git_src='https://raw.githubusercontent.com/maverickcdn/wicens/master/'
run_option="$1"
[ -z "$1" ] && run_option='tty' # used to show tty vs cron/test/wancall/fwupdate/send run
config_src="${script_dir}/wicens_user_config.wic" # user settings
update_src="${script_dir}/wicens_update_conf.wic" # core config file
history_src="${script_dir}/wicens_wan_history.wic" # historical wan ip change file
script_backup_file="${script_dir}/wicens_user_config.backup" # user settings backup
history_src_backup="${script_dir}/wicens_history_src.backup" # historical wan ip change file backup
reboot_email='/tmp/wicens_rebootmail.txt' # reboot notification mail text
fw_email='/tmp/wicens_fwmail.txt' # firmware update notification mail text
update_email='/tmp/wicens_updatemail.txt' # script update notification mail text
wanip_email='/tmp/wicens_wanipemail.txt' # wanip change notification mail text
mail_log="${script_dir}/wicens_email.log" # log file for sendmail/curl
script_lock="/tmp/wicens_lock.$run_option" # script temp lock file by argument
internet_lock="/tmp/wicens_internetlock.$run_option" # internet check lock, prevents killing processes waiting for internet
wicens_send_retry='/tmp/wicens_send.retry' # retry count file for send option
wicens_send_copy='/tmp/wicens_user_email.txt' # backup of email for send option in retries
wicens_update_retry='/tmp/wicens_update.retry' # retry count file for script update notification
wicens_fw_retry='/tmp/wicens_fw.retry' # retry count file for fw update notification
wicens_wanip_retry='/tmp/wicens_wanip.retry' # retry count file for wan ip change notification
wicens_reboot_retry='/tmp/wicens_reboot.retry' # retry count file for reboot notification
cred_loc="${script_dir}/.wicens_cred.enc"
cred_loc_bak="${cred_loc}bak"
amtm_email_conf='/jffs/addons/amtm/mail/email.conf'
amtm_cred_loc='/jffs/addons/amtm/mail/emailpw.enc'
amtm_d='L3Vzci9zYmluL29wZW5zc2wgMj4vZGV2L251bGwgYWVzLTI1Ni1jYmMgLXBia2RmMiAtZCAtaW4gL2pmZnMvYWRkb25zL2FtdG0vbWFpbC9lbWFpbHB3LmVuYyAtcGFzcyBwYXNzOmRpdGJhYm90LGlzb2kK'
user_d='L3Vzci9zYmluL29wZW5zc2wgZW5jIC1tZCBzaGE1MTIgLXBia2RmMiAtYWVzLTI1Ni1jYmMgLWQgLWEgLXBhc3MgcGFzczoiJChGX252cmFtIGJvYXJkbnVtIHwgL2Jpbi9zZWQgcy86Ly9nKSIK'
user_e='L3Vzci9zYmluL29wZW5zc2wgZW5jIC1tZCBzaGE1MTIgLXBia2RmMiAtYWVzLTI1Ni1jYmMgLWEgLXNhbHQgLXBhc3MgcGFzczoiJChGX252cmFtIGJvYXJkbnVtIHwgL2Jpbi9zZWQgcy86Ly9nKSIgfCB0ciAtZCAiXG4iCg=='
ip_regex='([0-9]{1,3}[\.]){3}[0-9]{1,3}'
current_wan_ip=''
building_settings=0
test_mode=0
sample_email=0
from_menu=0
config_updated=0
# in script and user configs 0=disabled 1=enabled
# SCRIPT MISC #########################################################################################################
F_git_get() {
case "$1" in
'file') curl -fsL --retry 2 --retry-delay 3 --connect-timeout 3 ${script_git_src}${script_name} ;;
'download') if curl -fsL --retry 2 --retry-delay 3 --connect-timeout 3 ${script_git_src}${script_name} -o /jffs/scripts/wicens.sh ; then F_chmod "$script_name_full" ; else return 1 ; fi ;;
'changelog') curl -fsL --retry 2 --retry-delay 3 --connect-timeout 3 ${script_git_src}CHANGELOG.md ;;
'hotfix') F_git_get changelog | sed -n "/^## $git_version/,/^## /p" | head -n -1 | sed 's/## //g' ;;
'update') F_git_get changelog | sed -n "/^## $git_version/,/^## $script_version/p" | head -n -1 | sed 's/## //g' ;;
esac
return 0
} # git_get
F_ctrlc() {
F_terminal_check_fail "Script interrupted..."
run_option='interrupt'
F_clean_exit
} # CTRL+C catch with trap
trap F_ctrlc INT HUP # trap ctrl+c exit clean
F_replace_var() { sed -i "1,/${1}=.*/{s/${1}=.*/${1}=\'${2}\'/;}" "$3" ;} # 1=var to change 2=new var string 3=file
F_chmod() { [ ! -x "$1" ] && chmod a+rx "$1" ;} # file permissions
F_crlf() { if grep -q $'\x0D' "$1" 2> /dev/null ; then dos2unix "$1" && F_log_terminal_ok "$(F_printfstr "$1" | awk -F/ '{print $(NF)}') contained CRLF, executed dos2unix" ; fi ;} # crlf
F_nvram() { nvram get "$1" ;}
F_printf() { printf '%b\n' "$1" ;} # printf recognize escape strings
F_printfstr() { printf '%s\n' "$1" ;} # printf raw string
F_printfp() { F_printfstr "$1" | /bin/sed 's@.*@
&
@' ;} # HTML email msg encapsulate line
F_printfpre() { F_printfstr "$1" | /bin/sed 's@.*@&
@' ;} # HTML email msg encapsulate line preserve whitespace
F_date() {
case "$1" in
'r') date -R ;; # RFC
's') date +'%s' ;; # seconds
'f') date +'%b %d %Y %T' ;; # abbr.mnth day year h:m:s
esac
} # date
# TERMINAL/LOGGING ####################################################################################################
F_terminal_show() { F_printf "$tTERMHASH $1" ;} # [~~~~]
F_terminal_padding() { F_printfstr '' ;} # blank line
F_terminal_separator() { F_printfstr '--------------------------------------------------------------------------------' ;} # 80 column
F_terminal_erase() { printf '%b' "$tBACK$tERASE" ;} # erase previous line
F_terminal_entry() { printf '%b' "$tTERMHASH $1" ;} # [~~~~] no new line
F_terminal_check() { printf '%b' "$tCHECK $1" ;} # [WAIT] no new line
F_terminal_check_ok() { F_printf "\r${tERASE}${tCHECKOK} $1" ;} # [ OK ]
F_terminal_check_fail() { F_printf "\r${tERASE}${tCHECKFAIL} $1" ;} # [FAIL]
F_term_waitdel() { printf '%b' "${tERASE}${tCHECK} $1 \r" ;} # used in countdowns (line re-write)
F_status_grn() { F_terminal_show "$(printf "%s%s|\n" "$1" "$(printf '%*s' "$((35 - ${#1}))" | tr ' ' '-')") ${tGRN}${2}${tCLR}" ;} # status enabled custom text
F_status_enabled() { F_terminal_show "$(printf "%s%s|\n" "$1" "$(printf '%*s' "$((35 - ${#1}))" | tr ' ' '-')") ${tGRN}Enabled${tCLR}" ;} # status Enabled
F_status_pass() { F_terminal_show "$(printf "%s%s|\n" "$1" "$(printf '%*s' "$((35 - ${#1}))" | tr ' ' '-')") ${tGRN}Passed${tCLR}" ;} # status pass
F_status_fail() { F_terminal_show "$(printf "%s%s|\n" "$1" "$(printf '%*s' "$((35 - ${#1}))" | tr ' ' '-')") ${tRED}Failed${tCLR}" ;} # status fail
F_status_disabled() { F_terminal_show "$(printf "%s%s|\n" "$1" "$(printf '%*s' "$((35 - ${#1}))" | tr ' ' '-')") ${tRED}Disabled${tCLR}" ;} # status Disabled
F_menu_enabled() { F_terminal_show "$1 ${tGRN}Enabled${tCLR}" ;} # menu enabled
F_menu_disabled() { F_terminal_show "$1 ${tRED}Disabled${tCLR}" ;} # menu disabled
F_edit() { F_terminal_show "$1 ${tGRN}${2}${tCLR}" ;} # edit menu
F_terminal_warning() { printf '%b%48s\n%48s\n%48s%b\n\n' "$tRED" "#################" "# WARNING #" "#################" "$tCLR" ;} # terminal warning
F_fail_entry() { F_terminal_check_fail "Invalid entry, any key to retry" && read -rsn1 && F_terminal_erase && continue ;} # terminal input invalid entry
F_log() {
case "$script_log" in
'1')
printf '%s' "$(F_date f) " >> "$script_log_loc"
logger -st "wicens[$$]" "$(F_printfstr "${run_option} : $1" )" 2>> "$script_log_loc"
;;
*) logger -t "wicens[$$]" "$(F_printfstr "${run_option} : $1" )"
;;
esac
} # logging
F_log_show() { F_log "$1" ; F_terminal_show "$1" ;} # log and print formatted
F_log_terminal_ok() { F_terminal_check_ok "$1" ; F_log "$1" ;} # log [ OK ]
F_log_terminal_fail() { F_terminal_check_fail "$1" ; F_log "$1" ;} # log [FAIL]
F_email_seperator() {
if [ "$sample_email" = 0 ]
then F_printfstr "
"
else F_printfstr '----------------------------------------------------------' # 58 column
fi
} # email_seperator
#requires being passed a line # for head to terminate on
F_terminal_entry_header() {
build_entry=1 # for F_status
cut_line=$((${1} + 2)) # add to passed line to account for top 2 lines of status page
F_terminal_header
F_status | head -n "$cut_line" | tail -n "$((cut_line - 2))" # remove top two lines of status page
F_terminal_separator
F_terminal_padding
} # terminal_entry_header
F_terminal_color() {
case "$opt_color" in
0)
tGRN=''
tRED=''
tPUR=''
tYEL=''
tCLR=''
;;
1)
tGRN="\033[1;32m"
tRED="\033[1;31m"
tPUR="\033[1;95m"
tYEL="\033[1;93m"
tCLR="\033[0m"
;;
esac
tERASE="\033[2K"
tBACK="\033[1A"
tCHECK="[${tYEL}WAIT${tCLR}]"
tCHECKOK="[${tGRN} OK ${tCLR}]"
tCHECKFAIL="[${tRED}FAIL${tCLR}]"
tTERMHASH="[${tPUR}~~~~${tCLR}]"
} # terminal_color
F_confirm() {
F_terminal_padding
while true ; do
case "$1" in
'correct') F_terminal_check "Is ${tGRN}${2}${tCLR} correct? | Y||y or N||n " ;;
*) F_terminal_check "$1 | Y||y or N||n " ;;
esac
read -rsn1 ynentry
case "$ynentry" in
Y|y) return 0 ;;
N|n) return 1 ;;
E|e) F_terminal_check_fail "Cancelled, exit selected" ; F_menu_exit ;;
*) F_fail_entry ;;
esac
break
done
} # confirm
F_wait() {
F_terminal_padding
wait_time="$1"
while [ "$wait_time" -ne '0' ] ; do
F_term_waitdel "Loading menu in $wait_time secs... any key to skip "
wait_time=$((wait_time - 1))
waiting=zzz
read -rsn1 -t1 waiting
[ ${#waiting} -le 1 ] && break
done
} # menu_wait
# MISC ################################################################################################################
F_random_num() {
if [ -z "$1" ] ; then random_max='30' ; else random_max="$1" ; fi
# pull uptime (w/ millisecond) as seed # for rng
awk -v min=1 -v max="$random_max" -v seed="$(awk '{print $1}' < /proc/uptime | tr -d '.')" 'BEGIN{srand(seed); print int(min+rand()*(max-min+1))}'
} # random_num
F_private_ip() {
# RFC 1918 defines private IP address ranges
# 10.0.0.0/8
# 172.16.0.0/12
# 192.168.0.0/16
# Also including 169.254.0.0/16 (used for Automatic Private IP Addressing)
grep -Eq '^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^169\.254\.'
} # private_ip as per ChatGPT
F_cgnat_ip(){
# test if the input is a RFC 6598 address for CGNAT
grep -Eq '^100\.(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
} # cgnat as per ChatGPT
F_uptime() {
router_uptime="$(awk '{print $1}' < /proc/uptime | cut -d'.' -f1)"
uptime_pretty="$(printf '%3dd %2dh %2dm %2dsec\n' $((router_uptime/86400)) $((router_uptime%86400/3600)) $((router_uptime%3600/60)) $((router_uptime%60)))"
} # uptime
# SCRIPT CONTROL ######################################################################################################
F_clean_exit() {
# reset terminal word wrap
printf '\033[?7h'
# if ctrlc kill any child process put in background (F_time-F_web_update_check)
[ "$run_option" = 'interrupt' ] && [ -n "$child_pid" ] && { for pid in $child_pid ; do kill "$child_pid" 2>/dev/null ; done ; }
# save last seen uptime
F_uptime
if [ "$router_uptime" -gt 600 ] && [ -f "$update_src" ] ; then
F_replace_var router_reboot_uptime "$router_uptime" "$update_src" # wait 10mins before saving uptime, if reboot notify enabled need to capture last known uptime
F_replace_var router_reboot_downtime "$(F_date s)" "$update_src" # save last seen current time to compare after reboot to estimate down time
fi
# pre lock removal restarts
[ "$1" = 'reload' ] && exec sh "$script_name_full" reload
# amtm style exit
if [ "$run_option" = 'tty' ] ; then
if [ "$1" != 'error' ] && [ "$1" != 'reset' ] ; then
F_terminal_header exit # amtm style exit, prevent other call types having terminal messages cleared
fi
fi
# remove all potential locks
for lock_to_remove in "$script_lock" "$ntp_lock" "$internet_lock" ; do
[ -f "$lock_to_remove" ] && rm -f "$lock_to_remove" && [ "$1" != 'reset' ] && F_terminal_check_ok "Removed ${lock_to_remove} lock file"
done
if [ -f "$script_lock" ] ; then
if [ "$$" != "$(sed -n '2p' "$script_lock")" ] ; then
F_log_terminal_ok "Lock file still present but not from this process..."
else
F_log_terminal_fail "Critical error - Failed to remove lock file"
exit 1
fi
fi
if [ "$1" = 'reset' ] ; then
exec sh "$script_name_full" # restart the script completely
elif [ "$1" = 'fail' ] || [ "$1" = 'error' ] ; then
exit 1 # for forwarder calls from other scripts
fi
F_printf "[${tGRN}EXIT${tCLR}] ${tYEL}Goodbye :) ${tCLR}"
F_terminal_padding
exit 0
} # clean_exit
F_menu_exit() {
F_terminal_padding
F_terminal_check "Any key to return to the Main Menu - E||e to exit to prompt"
read -rsn1 exitwait
case "$exitwait" in
E|e) F_terminal_check_ok "Exiting." ; F_clean_exit ;;
*) F_clean_exit reload ;;
esac
} # menu_exit
# FIRMWARE CHECK ######################################################################################################
F_firmware_check() {
F_fw_valid_version() {
if [ -z "$build_full" ] ; then
F_terminal_header
F_log_terminal_fail "Could not determine your firmware version from nvram"
rm -r "$script_dir" 2> /dev/null
F_terminal_check "Any key to exit..."
read -rsn 1
F_clean_exit
fi
[ "$(F_nvram firmver)" = '3.0.0.6' ] && return 0
case "$build_no" in
'386'|'388') return 0 ;;
'384') [ "$build_sub" -ge 15 ] && return 0 ;;
'374') [ "$john_sub" -ge 48 ] && return 0 ;;
*)
F_terminal_header
F_log_terminal_fail "Sorry this version of firmware is not compatible, please update to 384.15 or newer, or 374 LTS release 48 or newer to utilize this script"
F_terminal_padding
rm -r "$script_dir" 2> /dev/null
F_clean_exit
;;
esac
} # fw_valid_version
F_fw_write() {
pulled_device_name="$(F_nvram lan_hostname)"
pulled_lan_name="$(F_nvram lan_domain)"
device_model="$(F_nvram odmpid)"
lan_addr="$(F_nvram lan_ipaddr)"
[ -z "$device_model" ] && device_model="$(F_nvram productid)"
case "$build_no" in
'374') F_replace_var fw_build_sub "$john_sub" "$update_src" ;;
*) F_replace_var fw_build_sub "$build_sub" "$update_src" ;;
esac
F_replace_var fw_build_full "${build_no}.${build_sub}_${build_extend}" "$update_src"
F_replace_var fw_pulled_device_name "$pulled_device_name" "$update_src"
F_replace_var fw_pulled_lan_name "$pulled_lan_name" "$update_src"
F_replace_var fw_device_model "$device_model" "$update_src"
F_replace_var fw_build_no "$build_no" "$update_src"
F_replace_var fw_build_extend "$build_extend" "$update_src"
F_replace_var fw_lan_addr "$lan_addr" "$update_src"
F_replace_var fw_sw_mode "$software_mode" "$update_src"
source "$update_src"
case "$1" in
'fwupdate')
from_menu=1
F_terminal_header
F_log_show "Found new firmware version installed on router"
F_log_terminal_ok "core config v${update_settings_version} updated for new fw version ${build_full}_${build_extend}"
F_replace_var fw_notify_state 0 "$config_src" # reset Email notification after upgrading
F_menu_exit
;;
*)
case "$config_updated" in
1)
# for integrity_check updates
F_log_terminal_ok "core config v${update_settings_version} updated with router firmware information"
;;
*)
from_menu=1
installer=1
F_terminal_header
F_log "HI - wicens the WAN IP change EMAIL notification script has been installed"
F_printf "[ ${tGRN}HI${tCLR} ] ${tYEL}===== Welcome to wicens the WAN IP change Email notification script =====${tCLR}"
F_terminal_padding
F_terminal_check_ok "Created $script_dir directory"
F_terminal_check_ok "Created default user config v${current_user_config} for script v$script_version in $script_dir"
F_terminal_check_ok "Created default core config v$current_core_config for script v$script_version in $script_dir"
F_log_terminal_ok "Updated core config v${update_settings_version} with router firmware information"
F_alias
F_terminal_padding
F_terminal_check "Any key to continue to Main Menu"
read -rsn1
F_clean_exit reset
;;
esac
;;
esac
} # fw_write
# only if we havent checked fw already in the last 10 mins
if [ "$fw_nvram_check_diff" -gt "$max_fw_nvram_check" ] ; then
# start of fw check
# set fw vars check if written, check for update ##################################################################
F_replace_var fw_nvram_check_epoch "$(F_date s)" "$update_src"
build_full="$(F_nvram buildno)"
build_no="$(F_printf "$build_full" | cut -f1 -d '.')"
build_sub="$(F_printf "$build_full" | cut -f2 -d '.')"
build_extend="$(F_nvram extendno)"
software_mode="$(F_nvram sw_mode)"
# initial firmware compatibility check, first run will be unpopulated
if [ -z "$fw_build_no" ] || [ -z "$fw_build_sub" ] || [ -z "$fw_build_extend" ] || [ -z "$fw_build_full" ] ; then
if F_fw_valid_version ; then
# new install set install date
[ -z "$install_date" ] && F_replace_var install_date "$(F_date f)" "$config_src"
F_fw_write
fw_init=1
fi
fi
case "$fw_build_no" in
'374')
john_sub=${build_extend:0:2}
[ "$johnsub" != "$fw_build_sub" ] && F_fw_write fwupdate
;;
# check if user has upgraded firmware and update config, saving to config avoids numerous nvram calls every run not from terminal
*)
[ "$build_no" != "$fw_build_no" ] || [ "$build_sub" != "$fw_build_sub" ] || [ "$build_extend" != "$fw_build_extend" ] && F_fw_write fwupdate
[ "$fw_sw_mode" != "$software_mode" ] && F_replace_var fw_sw_mode "$software_mode" "$update_src"
;;
esac
fi
[ "$config_updated" = 1 ] && [ "$fw_init" != 1 ] && F_terminal_check_ok "core config firmware/router information current"
return 0
} # firmware_check
# ALIAS ###############################################################################################################
F_alias() {
case "$1" in
'remove')
if [ -f /jffs/configs/profile.add ] ; then
if grep -Fq "alias wicens=" /jffs/configs/profile.add ; then
sed -i "/alias wicens=/d" /jffs/configs/profile.add
[ ! -s /jffs/configs/profile.add ] && rm -f /jffs/configs/profile.add
F_log_terminal_ok "Removed alias from /jffs/configs/profile.add"
else
F_log_terminal_ok "No alias found in /jffs/configs/profile.add to remove"
fi
else
F_log_terminal_ok "No alias found in /jffs/configs/profile.add to remove"
fi
return 0
;;
esac
if [ ! -f /jffs/configs/profile.add ] ; then
F_printfstr "alias wicens=\"/bin/sh ${script_name_full}\" # added by wicens $(F_date r)" > /jffs/configs/profile.add
F_log_terminal_ok "Created /jffs/configs/profile.add and added entry for wicens"
elif ! grep -Fq "alias wicens=" /jffs/configs/profile.add ; then
F_printfstr "alias wicens=\"/bin/sh ${script_name_full}\" # added by wicens $(F_date r)" >> /jffs/configs/profile.add
F_log_terminal_ok "Added alias in /jffs/configs/profile.add for wicens"
fi
return 0
} # alias only checked on tty runs
# USER SETTINGS #######################################################################################################
#######################################################################################################################
F_default_user_create() {
{
F_printfstr "#!/bin/sh"
F_printfstr "# wicens user config file"
F_printfstr "build_settings_version='${current_user_config}'"
F_printfstr "###########################################################"
F_printfstr "saved_wan_ip="
F_printfstr "saved_wan_date='never'"
F_printfstr "saved_wan_epoch="
F_printfstr "###########################################################"
F_printfstr "# User config settings ####################################"
F_printfstr "user_login_addr="
F_printfstr "user_smtp_server="
F_printfstr "user_from_addr="
F_printfstr "user_send_to_addr="
F_printfstr "user_send_to_cc="
F_printfstr "user_msg_to='wicens user'"
F_printfstr "user_email_from='wicens script'"
F_printfstr "user_message_type="
F_printfstr "user_custom_subject="
F_printfstr "user_custom_subject_r="
F_printfstr "user_custom_subject_f="
F_printfstr "user_custom_subject_s="
F_printfstr "user_custom_text="
F_printfstr "user_custom_text_r="
F_printfstr "user_custom_text_f="
F_printfstr "user_custom_text_s="
F_printfstr "user_custom_script="
F_printfstr "user_custom_script_time="
F_printfstr "###########################################################"
F_printfstr "user_update_notification=0"
F_printfstr "user_fw_update_notification=0"
F_printfstr "user_reboot_notification=0"
F_printfstr "user_wanip_notification=0"
F_printfstr "user_wanip_monitor=0"
F_printfstr "###########################################################"
F_printfstr "last_cron_run='never'"
F_printfstr "cron_run_count=0"
F_printfstr "last_wancall_run='never'"
F_printfstr "wancall_run_count=0"
F_printfstr "last_wancall_log_count=0"
F_printfstr "last_ip_change='never'"
F_printfstr "ip_change_count=0"
F_printfstr "install_date="
F_printfstr "update_date='never'"
F_printfstr "created_date='never'"
F_printfstr "opt_color=1"
F_printfstr "log_cron_msg=1"
F_printfstr "amtm_import=0"
F_printfstr "protocol='smtps'"
F_printfstr "ssl_flag="
F_printfstr "###########################################################"
F_printfstr "# Created : $(F_date r)"
} > "$config_src"
F_log "Created default user config v${current_user_config} for v${script_version} in ${script_dir}"
} # create user config
F_default_update_create() {
{
F_printfstr "#!/bin/sh"
F_printfstr "# wicens core config file"
F_printfstr "update_settings_version='${current_core_config}'"
F_printfstr "###########################################################"
F_printfstr "fw_build_no="
F_printfstr "fw_build_sub="
F_printfstr "fw_build_extend="
F_printfstr "fw_pulled_device_name="
F_printfstr "fw_pulled_lan_name="
F_printfstr "fw_device_model="
F_printfstr "fw_build_full="
F_printfstr "fw_lan_addr="
F_printfstr "fw_sw_mode="
F_printfstr "###########################################################"
F_printfstr "update_avail='none'"
F_printfstr "update_cron_epoch=0"
F_printfstr "update_notify_state=0"
F_printfstr "fw_notify_state=0"
F_printfstr "reboot_notify_state=0"
F_printfstr "router_reboot_uptime="
F_printfstr "router_reboot_downtime="
F_printfstr "fw_nvram_check_epoch=0"
F_printfstr "# USER CAN EDIT BELOW SETTINGS ###########################"
F_printfstr "stun_max=3 # max number of stun lookup retries"
F_printfstr "getrealip_max=3 # max number of getrealip.sh retries"
F_printfstr "update_period=172800 # period between script update checks default:172800 (48 hrs)"
F_printfstr "wan_history_count=5 # number of historcal IPs in Email message default:5"
F_printfstr "retry_wait_period=14400 # period between failed email retries default:14400 (4 hrs)"
F_printfstr "max_email_retry=3 # max cron run retries before waiting for retry_period default:3"
F_printfstr "cron_check_freq=11 # minutes between cron checks default:11 (mins)"
F_printfstr "cron_string=\"*/\${cron_check_freq} * * * * ${script_name_full} cron\""
F_printfstr "cron_option=1 # run cron default:1 (on)"
F_printfstr "script_log=1 # independent wicens logging default:1 (on)"
F_printfstr "script_log_loc=\"${script_dir}/wicens.log\" # script independent log default:/jffs/addons/wicens/wicens.log"
F_printfstr "user_script_log=\"${script_dir}/user_script.log\" # user custom script log location"
F_printfstr "wan_event_wait=40 # sleep before compare after wan-event call default:40"
F_printfstr "reboot_notify_wait=20 # sleep before reboot notify services-start call default:20 (secs)"
F_printfstr "max_fw_nvram_check=600 # fw checks to nvram only every 10 minutes with tty default:600"
F_printfstr "dual_wan_check=1 # getrealip abort if dual wan enabled default:1"
F_printfstr "###########################################################"
F_printfstr "# add or change list of test sites in below function for internet test (9 max)"
F_printfstr "F_test_sites() {"
F_printfstr " F_printfstr \"google.com\""
F_printfstr " F_printfstr \"bing.com\""
F_printfstr " F_printfstr \"yahoo.com\""
F_printfstr " F_printfstr \"github.com\""
F_printfstr " F_printfstr \"asus.com\""
F_printfstr " F_printfstr \"sourceforge.net\""
F_printfstr " F_printfstr \"snbforums.com\""
F_printfstr " F_printfstr \"wikipedia.org\""
F_printfstr "}"
F_printfstr "###########################################################"
F_printfstr "F_stun_servers() {"
F_printfstr " F_printfstr \"stun.l.google.com:19302\""
F_printfstr " F_printfstr \"stun1.l.google.com:19302\""
F_printfstr " F_printfstr \"stun2.l.google.com:19302\""
F_printfstr " F_printfstr \"stun3.l.google.com:19302\""
F_printfstr " F_printfstr \"stun4.l.google.com:19302\""
F_printfstr "}"
F_printfstr "###########################################################"
F_printfstr "# use wicens main menu for editing email subject lines"
F_printfstr "wan_subject=\"WAN IP has changed on ASUS router \${fw_device_model} \${fw_pulled_device_name}\""
F_printfstr "reboot_subject=\"ASUS router \${fw_device_model} \${fw_pulled_device_name} has rebooted\""
F_printfstr "firmware_subject=\"ASUS router \${fw_device_model} \${fw_pulled_device_name} has Firmware Update available, version \${new_fw_ver_pretty}\""
F_printfstr "script_subject=\"Update available for wicens script on ASUS router \${fw_device_model} \${fw_pulled_device_name}\""
F_printfstr "###########################################################"
F_printfstr "# Created : $(F_date r)"
} > "$update_src"
F_log "Created default core config v${current_core_config} for v${script_version} in ${script_dir}"
} # create current_core
F_user_settings() {
[ ! -d "$script_dir" ] && mkdir "$script_dir" && F_log "Welcome to wicens - created $script_dir directory"
[ ! -f "$update_src" ] && F_default_update_create && F_chmod "$update_src"
[ ! -f "$config_src" ] && F_default_user_create && F_chmod "$config_src"
source "$config_src" # source user config file
source "$update_src" # source script config file
[ -n "$user_custom_subject" ] && user_custom_subject_decoded="$(F_printfstr "$user_custom_subject" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_subject_r" ] && user_custom_subject_decoded_r="$(F_printfstr "$user_custom_subject_r" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_subject_f" ] && user_custom_subject_decoded_f="$(F_printfstr "$user_custom_subject_f" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_subject_s" ] && user_custom_subject_decoded_s="$(F_printfstr "$user_custom_subject_s" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_text" ] && user_custom_text_decoded="$(F_printfstr "$user_custom_text" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_text_r" ] && user_custom_text_r_decoded="$(F_printfstr "$user_custom_text_r" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_text_f" ] && user_custom_text_f_decoded="$(F_printfstr "$user_custom_text_f" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_text_s" ] && user_custom_text_s_decoded="$(F_printfstr "$user_custom_text_s" | /usr/sbin/openssl base64 -d)"
[ -n "$user_custom_script" ] && user_custom_script_decoded="$(F_printfstr "$user_custom_script" | /usr/sbin/openssl base64 -d)"
case "$user_custom_script_time" in
i) user_script_call_time='immediate' ;;
w) user_script_call_time='wait' ;;
esac
case "$run_option" in
'tty')
fw_nvram_check_diff="$(($(F_date s) - fw_nvram_check_epoch))"
F_terminal_color # load user terminal settings
F_integrity_check # check config file status
;;
esac
F_settings_test # sets vars for valid config, enabled options etc
original_wan_ip="$(grep -F 'saved_wan_ip' 2> /dev/null < "$config_src" | grep -Eo "$ip_regex")"
original_wan_date="$(grep -F 'saved_wan_date' 2> /dev/null < "$config_src" | cut -d'=' -f2 | tr -d "'")"
original_wan_epoch="$(grep -F 'saved_wan_epoch' 2> /dev/null < "$config_src" | cut -d'=' -f2 | tr -d "'")"
# update_cron_epoch comes from core config (default=0) update_diff used in status and (time remaining to sched check) if enabled script updates
if [ "$update_cron_epoch" -gt 0 ]
then update_diff=$((run_epoch - update_cron_epoch))
else update_diff=$((update_period + 1))
fi
} # user settings
# MENU OPTIONS ########################################################################################################
#######################################################################################################################
F_opt_about() {
clear
{ # start of | more
F_printfstr " WICENS - WAN IP Change Email Notification Script " ; F_printfstr ''
F_printfstr "This script when configured has the ability to send Email notifications for "
F_printfstr "Option 3 - WAN IP Change (IPv4 only,DualWAN disabled) "
F_printfstr "Option 4 - Router reboot events "
F_printfstr "Option 5 - Firmware Updates (runs with built-in firmware notification check) "
F_printfstr "Option 6 - Script Updates (checks every 48hrs when enabled) "
F_printfstr "Script can call your own script when WAN IP change occurs (Option 7) "
F_printfstr "WAN IP change monitoring only Option 1 (auto enabled with Option 3) "
F_printfstr "Script can also be used to send your own generated Email files see "
F_printfstr "forwarder instructions further below " ; F_printfstr ''
F_printfstr "Supports GMail, Hotmail, Outlook, ISP based Email " ; F_printfstr ''
F_printfstr "Supports AsusWRT-Merlin built-in amtm Email configuration import " ; F_printfstr ''
F_printfstr "Script will function in Double NAT scenarios but does not support Dual WAN "
F_printfstr "Dual WAN check can be on/off by entering option dwd (default: on) " ; F_printfstr ''
F_printfstr "Script supports AP mode (non router), in this mode wan-event entries "
F_printfstr "are not created. Uses random google STUN server to retrieve WAN IP "
F_printfstr "SMTP Email send formats available: "
F_printfstr "curl - SSL (eg GMail port 465) # amtm default "
F_printfstr "sendmail - StartTLS v1.1 higher "
F_printfstr "sendmail - StartTLS v1 only "
F_printfstr "sendmail - SMTP plain auth (no encryption) "
F_printfstr "sendmail - ISP based (no password reqd, generally port 25) " ; F_printfstr ''
F_printfstr "IMPORTANT - If using GMail/Outlook you must use 2 factor authentication and "
F_printfstr "setup an assigned App password for this script to use. " ; F_printfstr ''
F_printfstr "IMPORTANT - Your Email address(es) are stored as plain text within this "
F_printfstr "script. Your Email password is encrypted and saved to router storage. "
F_printfstr "If you dont practice good security habits around your router ssh access, "
F_printfstr "this script might not be for you. " ; F_printfstr ''
F_printfstr "Script compares IP in nvram for wan0 to saved IP with wan-event connected "
F_printfstr "events and cron, cron is also a watchdog and monitors for failed Email "
F_printfstr "attempts. Should the nvram IP be invalid/private IP script will use firmware "
F_printfstr "built in ministun to retrieve your WAN IP using Google STUN server. " ; F_printfstr ''
F_printfstr "Router reboot Email contains last known uptime prior to reboot (saved w/cron)"
F_printfstr "and down time between power loss (last check with cron) and power up time " ; F_printfstr ''
F_printfstr "All cron/wan-event/services-start/update-notification entries needed for this"
F_printfstr "script are automatically created and removed with enable and disable options." ; F_printfstr ''
F_printfstr "NTP sync must occur on boot for proper script function " ; F_printfstr ''
F_printfstr "### Technical ### " ; F_printfstr ''
F_printfstr "Supports being used as an Email forwarder for other scripts, in your "
F_printfstr "script call /jffs/scripts/wicens.sh send {your email.txt path here} "
F_printfstr "ie. /jffs/scripts/wicens.sh send /tmp/email.txt "
F_printfstr "Use option fe (unlisted) in the menu to view a sample Email .txt file " ; F_printfstr ''
F_printfstr "When using wicens as an Email forwarder you can pass a second argument after "
F_printfstr "the Email text path as an alternate send to address different from what is "
F_printfstr "saved in the config ie. wicens send /path/email.txt myadd@mail.com " ; F_printfstr ''
F_printfstr "Should Email sending fail the script will retry 4 more times with cron "
F_printfstr "1/${cron_check_freq}mins) in ${update_period} second intervals. " ; F_printfstr ''
F_printfstr "Script generates a lock file /tmp/wicens_lock.\${run_option} to prevent "
F_printfstr "duplicate runs as well as /tmp/wicens_internet_lock.\${run_option} "
F_printfstr "when sending Email notifications. Script will automatically remove stale "
F_printfstr "lock files if original starting process no longer exists or lock file are "
F_printfstr "over age limit. " ; F_printfstr ''
F_printfstr "Sendmail/Curl output for Emails is saved to ${mail_log} for "
F_printfstr "debugging if needed. This file can be viewed by running this script and "
F_printfstr "select option L||l " ; F_printfstr ''
F_printfstr "Sendmail doesnt always return an error code on a misconfiguration so false "
F_printfstr "send success can occur. If script says Email has sent but no Email received "
F_printfstr "use option L||l from the Main Menu to read sendmail output for errors. " ; F_printfstr ''
F_printfstr "All messages sent to syslog are duplicated in ${script_log} "
F_printfstr "Including failed Email curl logs - Use option Z||z to view wicens.log " ; F_printfstr ''
F_printfstr "The script does not update its saved WAN IP until the script has completed "
F_printfstr "sending the notification so in the event of message failure it should run "
F_printfstr "again with next cron run and attempt to send again. " ; F_printfstr ''
F_printfstr "Using option 7 you can call your own script either immediately upon WAN IP "
F_printfstr "change detection, or wait until the Email message has been successfully sent."
F_printfstr "Script will be put in background as to not block this script. Your script "
F_printfstr "is called with the current WAN IP as an argument. " ; F_printfstr ''
F_printfstr "Output from a custom script set to run on WAN IP change is saved to "
F_printfstr "${user_script_log} " ; F_printfstr ''
F_printfstr "Hidden menu options "
F_printfstr "1f - forces build_settings menu (if amtm enabled) "
F_printfstr "fl - remove mail log file "
F_printfstr "vv - list out all settings from config files "
F_printfstr "fr - remove any found update "
F_printfstr "fe - show example Email text file for using wicens as Email forwarder "
F_printfstr "ul - show log from user script output when calling script on WAN IP change "
F_printfstr "rc - reset core config for notification controls, not user config "
F_printfstr "dw - disable/enable Dual WAN check " ; F_printfstr ''
F_printfstr "Every Sunday@6pm the script will log the # of times it ran with wan-event. " ; F_printfstr ''
F_printfstr "Thank you for using this script. " ; F_printfstr ''
F_printfstr "SNBforums thread https://www.snbforums.com/threads/wicens-wan-ip-change-email-notification-script.69294/" ; F_printfstr ''
F_printfstr "GitHub source https://github.com/maverickcdn/wicens "
} | more
} # about
F_opt_backup_restore() {
F_backup() {
if [ -f "$script_backup_file" ] ; then
while true ; do
F_terminal_warning
F_terminal_check "Backup file exists, Y||y to overwrite - Any key to return to Main Menu"
read -rsn1 configremove
case "$configremove" in
y|Y) rm -f "$script_backup_file" ; F_terminal_erase ;;
*) F_clean_exit reload ;;
esac
break
done
fi
F_terminal_check "Starting backup"
if cp "$config_src" "$script_backup_file" ; then
F_terminal_check_ok "Backup successful, saved to $script_backup_file"
F_printfstr "# Backup : by v${script_version} created $(F_date r)" >> "$script_backup_file"
if [ -f "$history_src" ] ; then
cp "$history_src" "$history_src_backup"
fi
if [ "$user_message_type" != 'smtp_isp_nopswd' ] ; then
if [ -f "$cred_loc" ] ; then
if cp "$cred_loc" "$cred_loc_bak" ; then
F_terminal_check_ok "Password backup successful"
else
F_terminal_check_fail"Error backing up password"
fi
else
case "$amtm_import" in
0) F_terminal_check_fail "Couldn't find password to backup" ;;
1) F_terminal_check_ok "amtm import enabled, skipping password backup" ;;
esac
fi
else
# cleanup if smtp_isp_nopswd
if [ -f "$cred_loc_bak" ] ; then
rm -f "$cred_loc_bak"
fi
fi
else
F_terminal_check_fail "Critical error, backup failed, could not output to $script_backup_file"
fi
[ "$1" = 'resetbackup' ] && F_terminal_check "Any key to continue..." && read -rsn1
} # backup
F_restore() {
source "$script_backup_file"
[ "$(F_printfstr "$build_settings_version" | cut -d'.' -f1)" -le 3 ] && [ "$amtm_import" = 0 ] && amtm_import=1 # v3-v4
restore=1
F_status | sed -n '1,/Script install/p'
F_terminal_show "File history:"
sed -n "/# Created/,/&/p" "$script_backup_file"
if ! F_confirm "Do you wish to restore this config?" ; then
F_terminal_check_ok "No received, exiting..."
F_menu_exit
fi
F_terminal_check_ok "Ok received"
F_terminal_check "Restoring backup"
if cp -f "$script_backup_file" "$config_src" ; then
F_printfstr "# Restored: by v${script_version} from backup on $(F_date r)" >> "$config_src"
if [ -f "$history_src_backup" ] ; then
cp "$history_src_backup" "$history_src"
fi
F_user_settings # reload
F_replace_var created_date "$(F_date f)" "$config_src"
if [ "$user_fw_update_notification" = 1 ] ; then
! F_notify_firmware check status && F_notify_firmware create
fi
if [ "$user_reboot_notification" = 1 ] ; then
! F_notify_reboot check status && F_notify_reboot create
fi
if [ "$user_update_notification" = 1 ] ; then
! F_notify_update check && F_notify_update create
fi
if [ "$user_wanip_notification" = 1 ] ; then
if [ "$status_cru" = 0 ] || [ "$status_srvstrt" = 0 ] || [ "$status_wanevent" = 0 ] ; then F_notify_wanip create ; fi
fi
F_settings_test
if [ "$user_message_type" != 'smtp_isp_nopswd' ] ; then
if [ -f "$cred_loc_bak" ] ; then
if cp -f "$cred_loc_bak" "$cred_loc" ; then
F_terminal_check_ok "Successfully restored backed up password"
else
F_terminal_check_fail "Error restoring backed up password"
fi
else
F_terminal_check_fail "Error, no backed up password found"
fi
fi
else
F_terminal_check_fail "Critical error copying backup to script"
fi
F_terminal_check_ok "Done restoring backup settings to script"
} # restore
# from F_reset, if valid config backup before reset
[ "$1" = 'resetbackup' ] && F_backup resetbackup && return 0
F_terminal_header
F_terminal_show "${tYEL}===== Backup/Restore Settings Menu =====${tCLR} E||e to exit"
F_terminal_padding
# no valid settings/backup
if [ "$status_email_cfg" = 0 ] && [ ! -f "$script_backup_file" ] ; then
F_terminal_warning
F_terminal_check_fail "Error invalid current settings and no backup found to restore"
F_terminal_padding
F_terminal_show "Use Menu option 1 to edit settings"
F_menu_exit
fi
while true ; do
if [ -f "$script_backup_file" ] ; then
F_terminal_check_ok "Backup found! R||r to restore settings D||d to delete backup"
else
F_terminal_check_fail "No backup found to restore"
fi
if [ "$status_email_cfg" = 1 ] ; then
F_terminal_check_ok "Valid config found! B||b to backup current config"
else
F_terminal_check_fail "No valid config to backup, Main Menu option 1 to add a config"
fi
F_terminal_padding
F_terminal_check "Selection : "
read -r bandrwait
case "$bandrwait" in
D|d)
F_terminal_erase
F_terminal_check_ok "Delete backup selected"
F_terminal_padding
F_terminal_warning
if ! F_confirm "This will delete your backup, are you sure?" ; then
F_terminal_check_ok "No received, exiting..."
F_menu_exit
fi
if [ -f "$script_backup_file" ] ; then
rm -f "$script_backup_file"
F_terminal_check_ok "Saved backup removed"
[ -f "$cred_loc_bak" ] && rm -f "$cred_loc_bak"
F_menu_exit
else
F_terminal_check_fail "Error, no saved backup to delete"
F_terminal_padding
F_terminal_check "Any key to return to the Main Menu"
read -rsn1
F_clean_exit reload
fi
;;
B|b)
if [ "$status_email_cfg" = 0 ] ; then
F_terminal_check_fail "Error, no valid config found to backup"
F_terminal_padding
F_terminal_check "Any key to return to the Main Menu"
read -rsn1
F_clean_exit reload
else
F_terminal_erase
F_terminal_check_ok "B selected for backup"
F_backup
F_menu_exit
fi
;;
R|r)
if [ -f "$script_backup_file" ] ; then
F_terminal_erase
F_terminal_check_ok "R selected for restore"
F_restore
F_printf "Any key to continue"
read -rsn 1
F_clean_exit reset
else
F_terminal_erase
F_terminal_check_fail "Invalid entry, no valid backup exists, any key to continue"
read -rsn1
F_opt_backup_restore
fi
;;
E|e) F_clean_exit reload ;;
*)
F_terminal_check_fail "Invalid entry, B/R/D - any key to retry, E return to Main Menu"
read -rsn1
case "$brinvalid" in
E|e) F_clean_exit reload ;;
*) F_opt_backup_restore ;;
esac
;;
esac
break
done
} # backup_restore
F_opt_color() {
case "$opt_color" in
1)
F_terminal_erase
F_terminal_padding
F_terminal_check "Setting script to no color mode"
F_replace_var opt_color '0' "$config_src"
F_terminal_check_ok "Set to no color mode, return to the Main Menu to view changes"
;;
0)
F_terminal_erase
F_terminal_padding
F_terminal_check "Setting script to color mode"
F_replace_var opt_color '1' "$config_src"
F_terminal_check_ok "Set to color mode, return to the Main Menu to view changes"
;;
esac
F_menu_exit
} # color
F_opt_count() {
count_entry=1
F_terminal_header
F_terminal_show "${tYEL}===== Counts Reset Menu =====${tCLR} E||e to Exit"
F_terminal_padding
F_status count | sed -n '/Cron run/,/Script configured/p'
F_terminal_separator
F_terminal_warning
F_terminal_show "This will reset cron/wan-event check counts and configured date"
F_terminal_show "as well as the option to reset WAN IP change records"
if F_confirm "Are you sure you wish to reset counts/dates?" ; then
F_terminal_check_ok "Ok received, resetting counts and configured date..."
F_replace_var cron_run_count 0 "$config_src"
F_replace_var last_cron_run 'never' "$config_src"
F_replace_var wancall_run_count 0 "$config_src"
F_replace_var last_wancall_run 'never' "$config_src"
F_replace_var last_wancall_log_count 0 "$config_src"
F_replace_var created_date "$(F_date f)" "$config_src"
F_log_terminal_ok "Reset cron count, wan-event count and configured date"
if [ "$last_ip_change" != 'never' ] ; then
if F_confirm "Reset last recorded WAN IP change date and total change count? " ; then
F_replace_var last_ip_change 'never' "$config_src"
F_replace_var ip_change_count 0 "$config_src"
F_log_terminal_ok "Reset last recorded WAN IP change date"
else
F_terminal_check_ok "Keeping WAN IP change records"
fi
else
F_terminal_check_ok "No IP change records to remove"
fi
if [ -f "$history_src" ] ; then
if F_confirm "Remove historical WAN IP change records?" ; then
rm -f "$history_src"
F_log_terminal_ok "Removed historical WAN IP change records"
else
F_terminal_check_ok "Keeping historical WAN IP change records"
fi
else
F_terminal_check_ok "No historical WAN IP change file found"
fi
else
F_terminal_check_ok "No received, exiting..."
fi
F_menu_exit
} # count
F_opt_forward() {
[ -n "$fwd_send_addr" ] && user_send_to_addr="$fwd_send_addr"
if [ ! -f "$wicens_send_retry" ] ; then
{
F_printfstr "#!/bin/sh"
F_printfstr "fwd_send_msg='${wicens_send_copy}'"
F_printfstr "fwd_send_addr='${user_send_to_addr}'"
F_printfstr "wicens_send_retry_time='${run_epoch}'"
F_printfstr "# Attempting to send $fwd_send_msg to $user_send_to_addr $(F_date r)"
} > "$wicens_send_retry"
F_chmod "$wicens_send_retry"
cp "$fwd_send_msg" "$wicens_send_copy" 2> /dev/null # copy incase send fails and user has email removed in their script
else
F_printfstr "# Attempting to send $fwd_send_msg to $user_send_to_addr $(F_date r)" >> "$wicens_send_retry"
fi
mail_file="$fwd_send_msg"
[ -f "$mail_log" ] && rm -f "$mail_log"
F_internet_check send
if ! F_send_email ; then
F_log_terminal_fail "Error, failed to send $fwd_send_msg Email to $user_send_to_addr"
user_pswd=''
rm -f "$mail_file"
return 1
fi
user_pswd=''
rm -f "$mail_file"
rm -f "$wicens_send_retry"
rm -f "$wicens_send_copy"
F_log_terminal_ok "Success, finished sending $fwd_send_msg Email to $user_send_to_addr"
return 0
} # forward
F_opt_mail_log() {
if [ -f "$mail_log" ] ; then
more < "$mail_log"
F_terminal_padding
F_terminal_check_ok "End of contents."
F_menu_exit
else
F_terminal_check_fail "No log file found"
F_menu_exit
fi
} # mail_log
F_opt_reset() {
F_terminal_header
F_terminal_show "${tYEL}===== Script Reset Menu =====${tCLR} E||e to Exit"
F_terminal_padding
F_terminal_warning
if [ "$status_email_cfg" = 1 ] && [ "$backup_skip" != "1" ] ; then
F_terminal_check_ok "Found valid config"
F_terminal_padding
F_terminal_show "You're about to reset, would you like to make a backup?"
F_terminal_padding
while true ; do
F_terminal_check "B||b to create a backup R||r to reset without backup E||e to exit"
read -rsn1 backup_wait
case "$backup_wait" in
B|b) F_terminal_header ; F_terminal_check_ok "Creating backup" ; F_opt_backup_restore resetbackup ;;
R|r) break ;;
E|e) F_clean_exit reload ;;
*) F_fail_entry ;;
esac
break
done
backup_skip=1
F_opt_reset
fi
F_terminal_show "This will reset wicens to default and remove all saved settings and "
F_terminal_show "records including entires in services-start, wan-event, cron"
F_terminal_show "and update-notification"
if F_confirm "Are you sure you wish to reset?" ; then
F_terminal_check_ok "Ok received, resetting..."
else
F_terminal_check_ok "No received, exiting..."
F_menu_exit
fi
F_notify_firmware remove un
F_notify_reboot remove un
F_auto_run removeall
[ -f "$cred_loc" ] && rm -f "$cred_loc" && F_log_terminal_ok "Removed saved password"
[ -f "$config_src" ] && rm -f "$config_src" && F_log_terminal_ok "Reset user config to default"
[ -f "$update_src" ] && rm -f "$update_src" && F_log_terminal_ok "Reset core config to default"
[ -f "$history_src" ] && rm -f "$history_src" && F_log_terminal_ok "Removed WAN IP change history"
F_log_terminal_ok "Done, script reset to default"
[ -f "$mail_log" ] && rm -f "$mail_log"
F_terminal_padding
F_terminal_check "Any key to continue"
read -rsn1
F_clean_exit reset
} # reset
F_opt_sample() {
if [ -n "$1" ] ; then
sample_email=1
run_option='sample'
clear
F_terminal_show "Sample Email output:"
F_terminal_padding
if [ "$1" = 'reboot' ] ; then
F_reboot_email_msg
elif [ "$1" = 'wanip' ] ; then
current_wan_ip='111.222.33.44' # fake for email
test_mode=1
F_wanip_email_msg
test_mode=0
elif [ "$1" = 'firmware' ] ; then
new_fw_ver_pretty='xxx.xx_x'
firmware_subject="Asus router ${fw_device_model} ${fw_pulled_device_name} has Firmware Update available, version ${new_fw_ver_pretty}"
F_fw_update_email_msg
fi
sed '1,2!s/<[^>]*>//g' < "$mail_file" | awk '{ while (length($0) > 58) { print substr($0, 1, 58); $0 = substr($0, 59) } print $0 }'
sample_email=0
run_option='tty'
rm -f "$mail_file"
F_terminal_show "End of Email output"
if [ "$building_settings" = 0 ]
then F_menu_exit
else return 0
fi
else
[ "$building_settings" = 1 ] && F_opt_sample wanip && return 0
F_terminal_header
F_terminal_show "${tYEL}===== Sample Email Menu =====${tCLR} E||e to exit"
F_terminal_padding
F_terminal_show "Which sample Email would you like to view?"
F_terminal_padding
F_terminal_show " 1) WAN IP 2) Reboot 3) Firmware"
F_terminal_padding
F_terminal_check "Selection: "
while true ; do
read -r sampleselect
case "$sampleselect" in
1) F_opt_sample wanip ;;
2) F_opt_sample reboot ;;
3) F_opt_sample firmware ;;
E|e) F_clean_exit reload ;;
*)
F_terminal_erase
F_terminal_check_fail "Invalid Entry, any key to retry"
read -rsn1
F_opt_sample
;;
esac
return 1
done
fi
} # sample
F_opt_script() {
if [ "$1" = 'remove' ] ; then
F_replace_var user_custom_script '' "$config_src"
F_replace_var user_custom_script_time '' "$config_src"
user_custom_script_decoded=
user_script_call_time=
user_custom_script=
user_custom_script_time=
return 0
fi
F_terminal_header
F_terminal_show "${tYEL}===== Custom Script Path Entry Menu =====${tCLR} E||e to exit"
F_terminal_padding
if [ "$status_wanipmon" = 0 ] ; then
F_terminal_check_fail "WAN IP monitoring or WAN IP notifications are not enabled"
F_terminal_padding
F_terminal_show "Please enable either to add WAN IP change script"
F_menu_exit
fi
F_ready_check options
if [ -z "$user_custom_script" ] ; then
while true ; do
F_terminal_show "Do you want your custom script to execute immediately on detection"
F_terminal_show "of WAN IP change or wait until notification message has been sent"
F_terminal_show "If only WAN IP monitoring is enabled (not WAN IP Email) use immediate"
F_terminal_padding
F_terminal_show "${tGRN}w${tCLR} for wait - ${tGRN}i${tCLR} for immediately "
F_terminal_padding
F_terminal_entry "Selection: "
read -r user_script_wait_entry
F_terminal_padding
case "$user_script_wait_entry" in
w|i)
case "$user_script_wait_entry" in
i) user_script_call_time='immediate' ;;
w)
if [ "$user_wanip_notification" != '1' ] ; then
F_terminal_check_fail "Error, WAN IP notifications are not enabled, any key to return"
read -rsn1
F_opt_script
fi
user_script_call_time='wait'
;;
esac
F_replace_var user_custom_script_time "$user_script_wait_entry" "$config_src"
F_terminal_check_ok "Done writing custom script execute time $user_script_wait_entry to script"
user_custom_script_time="$user_script_wait_entry"
;;
E|e) F_clean_exit reload ;;
*)
F_terminal_check_fail "Invalid entry, any key to retry"
read -rsn1
F_opt_script
;;
esac
break
done
F_terminal_padding
F_terminal_check "Any key to continue..."
read -rsn1
F_terminal_header
F_terminal_show "${tYEL}--- Custom Script Path Entry Menu ---${tCLR} E||e to exit"
F_terminal_padding
F_terminal_show "Script execution set to : ${tGRN}$user_custom_script_time${tCLR}"
F_terminal_padding
F_terminal_show "Enter the full path to your script to be called"
F_terminal_show "eg. /jffs/scripts/customscript.sh"
F_terminal_padding
F_terminal_entry "Path : "
read -r user_custom_script_entry
case "$user_custom_script_entry" in
E|e)
F_replace_var user_custom_script_time '' "$config_src"
user_script_call_time=
F_menu_exit
;;
"")
F_terminal_check_fail "Script path cannot be empty - Any key to retry"
read -rsn1
F_opt_script
;;
esac
if F_confirm correct "$user_custom_script_entry" ; then
if [ ! -f "$user_custom_script_entry" ] ; then
F_terminal_check_fail "Error - could not locate custom script $user_custom_script_entry"
F_terminal_padding
F_terminal_show "Any key to return to the Main Menu"
F_replace_var user_custom_script_time '' "$config_src"
user_script_call_time=
read -rsn1
F_clean_exit reload
else
F_terminal_check_ok "Success - found file, saving custom script path to execute"
fi
custom_script_encoded="$(F_printfstr "$user_custom_script_entry" | /usr/sbin/openssl base64 | tr -d '\n')" # base64 no worries of sed conflicts
if F_replace_var user_custom_script "$custom_script_encoded" "$config_src" ; then
F_terminal_check_ok "Done writing custom script path to wicens"
user_custom_script="$user_custom_script_entry"
F_crlf "$user_custom_script"
F_chmod "$user_custom_script"
else
F_terminal_check_fail "Error, sed failed writing custom script path to wicens script"
fi
return 0
else
F_replace_var user_custom_script_time '' "$config_src"
return 1
fi
else
F_terminal_show "Custom script path already set"
F_terminal_padding
F_terminal_show "${tGRN}${user_custom_script_decoded}${tCLR}"
F_terminal_padding
while true ; do
F_terminal_check "Y||y keep - N||n enter new - R||r remove current "
read -rsn1 yesornowremove
case "$yesornowremove" in
Y|y) F_terminal_check_ok "Keeping currently saved custom script path" ;;
N|n) user_custom_script='' ; return 1 ;;
R|r) F_opt_script remove ;;
E|e) F_clean_exit reload ;;
*)
F_terminal_check_fail "Invalid entry, Y||y N||n R||r - Any to key to retry"
read -rsn1
F_terminal_erase
continue
;;
esac
break
done
fi
} # script
F_opt_subject_select() {
F_terminal_header
F_terminal_show "${tYEL}===== Custom Subject Menu =====${tCLR} E||e to exit"
F_terminal_padding
F_ready_check options
F_terminal_show "Enter which Email subject line you wish to customize"
F_terminal_padding
[ -n "$user_custom_subject_decoded" ] && sw="${tGRN}"
[ -n "$user_custom_subject_decoded_r" ] && sr="${tGRN}"
[ -n "$user_custom_subject_decoded_f" ] && sf="${tGRN}"
[ -n "$user_custom_subject_decoded_s" ] && ss="${tGRN}"
F_terminal_show " 1) ${sw}WAN IP${tCLR} 2) ${sr}Reboot${tCLR} 3) ${sf}Firmware${tCLR} 4) ${ss}Script${tCLR}"
F_terminal_padding
subject_select=
while true ; do
F_terminal_check "Selection: "
read -r subject_pick
case "$subject_pick" in
1|2|3|4) break ;;
e|E) F_clean_exit reload ;;
*) F_terminal_erase ; F_fail_entry ;;
esac
done
if [ "$subject_pick" = 1 ] ; then
subject_select=user_custom_subject
sub_dec="$user_custom_subject_decoded"
current_sub="$wan_subject" # var name for subjects
subject_id='WAN IP'
elif [ "$subject_pick" = 2 ] ; then
subject_select=user_custom_subject_r
sub_dec="$user_custom_subject_decoded_r"
current_sub="$reboot_subject"
subject_id='Reboot'
elif [ "$subject_pick" = 3 ] ; then
subject_select=user_custom_subject_f
sub_dec="$user_custom_subject_decoded_f"
current_sub="$firmware_subject"
subject_id='Firmware'
elif [ "$subject_pick" = 4 ] ; then
subject_select=user_custom_subject_s
sub_dec="$user_custom_subject_decoded_s"
current_sub="$script_subject"
subject_id='Script update'
fi
F_opt_subject
}
F_opt_subject() {
F_terminal_header
F_terminal_show "${tYEL}===== Custom Subject Menu =====${tCLR} E||e to exit"
F_terminal_padding
F_ready_check options
F_terminal_show "Custom Subject msg type : ${tGRN}$subject_id${tCLR}"
F_terminal_padding
if eval "[ -z \"\${$subject_select}\" ]" ; then
F_terminal_show "Enter the text for a custom Email Subject line you wish to use"
F_terminal_padding
F_terminal_show "Current subject: ${tGRN}${current_sub}${tCLR}"
F_terminal_padding
if [ "$subject_pick" = 1 ] ; then
F_terminal_show "If you wish to use the new or old WAN IP, add the variable names"
F_terminal_show "\$current_wan_ip and \$saved_wan_ip to your text (like shown)"
F_terminal_show "Model of router is \$fw_device_model"
F_terminal_show "Router device name is \$fw_pulled_device_name"
F_terminal_show "Router domain name is \$fw_pulled_lan_name"
F_terminal_show "LAN IP is \$fw_lan_addr"
F_terminal_padding
fi
F_terminal_entry "Subject: "
read -r user_custom_subject_entry
[ -z "$user_custom_subject_entry" ] && return 1
case "$user_custom_subject_entry" in
E|e) F_clean_exit reload ;;
esac
if F_confirm correct "$user_custom_subject_entry" ; then
custom_subject_encoded="$(F_printfstr "$user_custom_subject_entry" | /usr/sbin/openssl base64 | tr -d '\n')"
if F_replace_var "$subject_select" "$custom_subject_encoded" "$config_src" ; then
#user_custom_subject="$user_custom_subject_entry"
F_terminal_check_ok "Done, ${subject_select} set to : ${user_custom_subject_entry}"
else
F_terminal_check_fail "Error, sed failed to write custom subject to script"
F_menu_exit
fi
else
return 1
fi
else
F_terminal_show "Custom subject already set :"
F_terminal_padding
F_terminal_show "${tYEL}${sub_dec}${tCLR}"
F_terminal_padding
while true; do
F_terminal_check "Y||y keep - N||n enter new - R||r remove current "
read -rsn1 yesornowremovesub
case "$yesornowremovesub" in
Y|y) F_terminal_check_ok "Keeping currently saved custom Email subject text" ;;
N|n) eval "$subject_select=\"\"" ; return 1 ;;
R|r)
if F_replace_var "$subject_select" '' "$config_src" ; then
F_terminal_check_ok "Custom subject text cleared"
eval "$subject_select="
else
F_terminal_check_fail "Error, sed failed to clear custom subject text"
F_menu_exit
fi
;;
E|e) F_clean_exit reload ;;
*)
F_terminal_check_fail "Invalid entry, Y||y N||n R||r - Any to key to retry"
read -rsn1
F_terminal_erase
continue
;;
esac
break
done
fi
} # subject
F_opt_test() {
F_terminal_header
F_terminal_show "${tYEL}===== Test Email Menu =====${tCLR} E||e to exit"
F_terminal_padding
F_terminal_show "Choose the Email message type you'd like to receive"
F_terminal_padding
F_terminal_show "1) WAN IP 2) Router Reboot 3) Firmware"
F_terminal_padding
F_terminal_check "Selection (1/2/3) : "
read -r emailtesttype
case "$emailtesttype" in
1|2|3)
F_terminal_header
F_ready_check options
F_terminal_check_ok "Started Email Test message to ${user_send_to_addr}"
test_mode=1
run_option='test'
case "$emailtesttype" in
1)
current_wan_ip='x.x.x.x TEST'
F_wanip_email_msg # return to menu or exit in F_wanip_email
;;
2) F_reboot_email_msg ; F_menu_exit ;;
3) F_fw_update_email_msg ; F_menu_exit ;;
esac
;;
e|E) F_clean_exit reload ;;
*) F_fail_entry ;;
esac
} # test
F_opt_text_select() {
F_terminal_header
F_terminal_show "${tYEL}===== Custom Email Text Entry Menu =====${tCLR} E||e to exit"
F_terminal_padding
F_ready_check options
F_terminal_show "Enter which Email you wish to add custom text to"
F_terminal_padding
[ -n "$user_custom_text_decoded" ] && sw="${tGRN}"
[ -n "$user_custom_text_r_decoded" ] && sr="${tGRN}"
[ -n "$user_custom_text_f_decoded" ] && sf="${tGRN}"
[ -n "$user_custom_text_s_decoded" ] && ss="${tGRN}"
F_terminal_show " 1) ${sw}WAN IP${tCLR} 2) ${sr}Reboot${tCLR} 3) ${sf}Firmware${tCLR} 4) ${ss}Script${tCLR}"
F_terminal_padding
text_select=
while true ; do
F_terminal_check "Selection: "
read -r text_pick
case "$text_pick" in
1|2|3|4) break ;;
e|E) F_clean_exit reload ;;
*) F_terminal_erase ; F_fail_entry ;;
esac
done
if [ "$text_pick" = 1 ] ; then
text_select=user_custom_text
text_dec="$user_custom_text_decoded"
text_id='WAN IP'
elif [ "$text_pick" = 2 ] ; then
text_select=user_custom_text_r
text_dec="$user_custom_text_r_decoded"
text_id='Reboot'
elif [ "$text_pick" = 3 ] ; then
text_select=user_custom_text_f
text_dec="$user_custom_text_f_decoded"
text_id='Firmware'
elif [ "$text_pick" = 4 ] ; then
text_select=user_custom_text_s
text_dec="$user_custom_text_s_decoded"
text_id='Script update'
fi
F_opt_text
}
F_opt_text() {
F_terminal_header
F_terminal_show "${tYEL}===== Custom Text Entry Menu =====${tCLR} E||e to exit"
F_terminal_padding
F_terminal_show "Current text msg type: ${tGRN}${text_id}${tCLR}"
F_terminal_padding
if eval "[ -z \"\${$text_select}\" ]" ; then
#if [ -z "$user_custom_text" ] ; then
F_terminal_show "Enter your line of custom plain text to add to the Email message"
F_terminal_show "eg. Router hidden in moms closet, 2 vpn clients to update"
F_terminal_show "Entry must be one line, can use \\\n to create new line in Email msg"
F_terminal_padding
F_terminal_entry "Text : "
read -r user_custom_text_entry
F_terminal_padding
# ensure we empty any saved vars if brought here by N new entry but left entry blank
[ -z "$user_custom_text_entry" ] && F_replace_var user_custom_text '' "$config_src" && return 1
case "$user_custom_text_entry" in
E|e) F_clean_exit reload ;;
esac
if F_confirm correct "$user_custom_text_entry" ; then
custom_text_encoded="$(F_printfstr "$user_custom_text_entry" | /usr/sbin/openssl base64 | tr -d '\n')" # base64 no worries of sed conflicts
F_replace_var "$text_select" "$custom_text_encoded" "$config_src"
F_terminal_check_ok "Done writing custom text to script"
else
return 1
fi
else
F_terminal_show "Custom text already set :"
F_terminal_padding
F_terminal_show "${tYEL}${text_dec}${tCLR}"
F_terminal_padding
while true ; do
F_terminal_check "Y||y keep - N||n enter new - R||r remove current "
read -rsn1 yesornowremove
case "$yesornowremove" in
Y|y) F_terminal_check_ok "Keeping currently saved custom text" ;;
N|n) eval "$text_select=\"\"" ; return 1 ;;
R|r)
F_replace_var "$text_select" '' "$config_src"
F_terminal_check_ok "Done, custom text cleared"
user_custom_text=''
;;
E|e) F_clean_exit reload ;;
*)
F_terminal_check_fail "Invalid entry, Y||y N||n R||r - Any to key to retry"
read -rsn1
F_terminal_erase
continue
;;
esac
break
done
fi
} # custom_text
F_opt_uninstall() {
F_terminal_header
F_terminal_warning
F_terminal_show "This will remove the wicens script ENTIRELY from your system"
F_terminal_show "And any backup configs"
F_terminal_padding
while true ; do
F_terminal_show "Are you sure you wish to uninstall? Type DELETE || delete"
F_terminal_padding
F_terminal_check "Confirm : "
read -r uninstall_wait
case "$uninstall_wait" in
'DELETE'|'delete')
F_terminal_header exit
F_terminal_check_ok "Uninstalling..."
F_notify_firmware remove un
F_notify_reboot remove un
F_auto_run removeall
F_alias remove
rm -f /tmp/wicens*
rm -f "$script_name_full"
[ -f "$script_log_loc" ] && rm -f "$script_log_loc" # non default location
F_log_terminal_ok "Removed wicens files from RAM (/tmp)"
F_log_terminal_ok "Removed /jffs/addons/wicens directory and /jffs/scripts/wicens.sh"
F_log_terminal_ok "Done, wicens has been uninstalled completely"
F_printf "[${tGRN}EXIT${tCLR}] Goodbye"
rm -r "$script_dir"
F_terminal_padding
exit 0
;;
*)
F_terminal_erase
F_terminal_check_fail "Must type DELETE to uninstall"
F_menu_exit
;;
esac
break
done
} # uninstall
# NOTIFY OPTIONS ######################################################################################################
#######################################################################################################################
F_notify_firmware() {
case "$1" in
'check')
status_fw=0
if grep -Fq "$script_name_full fwupdate" /jffs/scripts/update-notification 2> /dev/null ; then
[ "$status_email_cfg" = 1 ] && [ "$user_fw_update_notification" = 1 ] && \
[ "$status_cru" = 1 ] && [ "$status_srvstrt" = 1 ] && status_fw=1
return 0
fi
return 1
;;
'create')
if [ -f /jffs/scripts/update-notification ] ; then
F_crlf '/jffs/scripts/update-notification'
F_chmod '/jffs/scripts/update-notification'
if ! grep -Fq '#!/bin/sh' /jffs/scripts/update-notification ; then
sed -i '1 i\#!/bin/sh' /jffs/scripts/update-notification
F_log_terminal_fail "Your update-notification does not contain a '#!/bin/sh'"
F_log_terminal_ok "Added #!/bin/sh to top of update-notification file"
fi
{
F_printfstr "nohup sh ${script_name_full} fwupdate & wicenspid=\$! # added by wicens $(F_date r)"
F_printfstr "/usr/bin/logger -t \"update-notification[\$\$]\" \"Started wicens with pid \${wicenspid}\" # added by wicens $(F_date r)"
} >> /jffs/scripts/update-notification
F_log_terminal_ok "Created entry in /jffs/scripts/update-notification for fw update"
else
{
F_printfstr '#!/bin/sh'
F_printfstr "# Created by $script_name_full for WAN IP change notification # added by wicens $(F_date r)"
F_printfstr "nohup sh ${script_name_full} fwupdate & wicenspid=\$! # added by wicens $(F_date r)"
F_printfstr "/usr/bin/logger -t \"update-notification[\$\$]\" \"Started wicens with pid \${wicenspid}\" # added by wicens $(F_date r)"
} > /jffs/scripts/update-notification
F_chmod '/jffs/scripts/update-notification'
F_log_terminal_ok "Created /jffs/scripts/update-notification and added entry for fw update"
fi
F_replace_var user_fw_update_notification 1 "$config_src"
F_auto_run create2
F_log_terminal_ok "Enabled Firmware update Email notification"
return 0
;;
'remove')
if [ -f /jffs/scripts/update-notification ] ; then
if grep -Fq "$script_name_full fwupdate" /jffs/scripts/update-notification ; then
sed -i '/added by wicens/d' /jffs/scripts/update-notification
F_log_terminal_ok "Removed entry in update-notification for firmware updates"
else
F_log_terminal_ok "No entry in /jffs/scripts/update-notification for fw to remove"
fi
if [ "$(wc -l < /jffs/scripts/update-notification)" -eq 1 ] ; then
if grep -Fq '#!/bin/sh' /jffs/scripts/update-notification ; then
rm -f /jffs/scripts/update-notification
F_log_terminal_ok "/jffs/scripts/update-notification appears empty, removed file"
fi
fi
else
F_terminal_check_ok "No entry in /jffs/scripts/update-notification for fwupdate - file doesn't exist"
fi
F_replace_var user_fw_update_notification 0 "$config_src"
user_fw_update_notification=0
[ "$2" != 'un' ] && F_log_terminal_ok "Disabled Firmware update Email notifcation"
if [ "$user_wanip_notification" = 0 ] && [ "$user_reboot_notification" = 0 ] && [ "$user_update_notification" = 0 ] && [ "$user_wanip_monitor" = 0 ] ; then
if [ "$2" != 'un' ] ; then
F_auto_run remove2
fi
fi
return 0
;;
esac
F_terminal_show "${tYEL}===== Firmware update notification enable/disable =====${tCLR}"
if [ "$fw_build_no" -eq 374 ] ; then
F_terminal_show "Sorry, this version of firmware is not compatible"
F_menu_exit
fi
if [ "$status_email_cfg" -eq 1 ] && [ "$user_fw_update_notification" -eq 0 ] ; then
F_notify_firmware create
elif [ "$user_fw_update_notification" -eq 1 ] ; then
F_notify_firmware remove
else
F_terminal_padding
F_terminal_check_fail "Error - invalid Email settings, use Main Menu to add settings"
fi
F_menu_exit
} # notify_firmware
F_notify_reboot() {
case "$1" in
'check')
status_reboot=0
if grep -Fq "$script_name_full reboot" /jffs/scripts/services-start 2> /dev/null ; then
[ "$status_email_cfg" = 1 ] && [ "$user_reboot_notification" = 1 ] && \
[ "$status_cru" = 1 ] && [ "$status_srvstrt" = 1 ] && status_reboot=1
return 0
fi
return 1
;;
'create')
if [ -f /jffs/scripts/services-start ] ; then
F_crlf '/jffs/scripts/services-start'
F_chmod '/jffs/scripts/services-start'
if ! grep -Fq '#!/bin/sh' /jffs/scripts/services-start ; then
sed -i '1 i\#!/bin/sh' /jffs/scripts/services-start
F_log_terminal_fail "Your services-start does not contain a '#!/bin/sh'"
F_log_terminal_ok "Added #!/bin/sh to top of services-start file"
fi
{
F_printfstr "nohup sh ${script_name_full} reboot & wicenspid=\$! # added by reboot wicens $(F_date r)"
F_printfstr "/usr/bin/logger -t \"services-start[\$\$]\" \"Started wicens for reboot notification with pid \${wicenspid}\" # added by reboot wicens $(F_date r)"
} >> /jffs/scripts/services-start
F_log_terminal_ok "Added entry to /jffs/scripts/services-start for reboot"
else
{
F_printfstr "#!/bin/sh"
F_printfstr "# Created by ${script_name_full} for router reboot notification # added by reboot wicens $(F_date r)"
F_printfstr "nohup sh ${script_name_full} reboot & wicenspid=\$! # added by reboot wicens $(F_date r)"
F_printfstr "/usr/bin/logger -t \"services-start[\$\$]\" \"Started wicens for reboot notification with pid \${wicenspid}\" # added by reboot wicens $(F_date r)"
} > /jffs/scripts/services-start
F_chmod '/jffs/scripts/services-start'
F_log_terminal_ok "Created /jffs/scripts/services-start and added entry for reboot"
fi
F_replace_var user_reboot_notification 1 "$config_src"
user_reboot_notification=1
F_auto_run create2
F_log_terminal_ok "Enabled router reboot Email notification"
return 0
;;
'remove')
if [ -f /jffs/scripts/services-start ] ; then
if grep -Fq "${script_name_full} reboot" /jffs/scripts/services-start ; then
sed -i '/added by reboot wicens/d' /jffs/scripts/services-start
F_log_terminal_ok "Removed entry in /jffs/scripts/services-start for reboot"
else
F_terminal_check_ok "No entry in /jffs/scripts/services-start for reboot"
fi
if [ "$(wc -l < /jffs/scripts/services-start )" -eq 1 ] ; then
if grep -Fq '#!/bin/sh' /jffs/scripts/services-start ; then
F_log_terminal_ok "/jffs/scripts/services-start appears empty, removing file"
rm -f /jffs/scripts/services-start
fi
fi
else
F_terminal_check_ok "No entry in /jffs/scripts/services-start for reboot, file doesn't exist"
fi
F_replace_var user_reboot_notification 0 "$config_src"
user_reboot_notification=0
[ "$2" != 'un' ] && F_log_terminal_ok "Disabled router reboot Email notification"
if [ "$user_wanip_notification" = 0 ] && [ "$user_fw_update_notification" = 0 ] && [ "$user_update_notification" = 0 ] && [ "$user_wanip_monitor" = 0 ] ; then
if [ "$2" != 'un' ] ; then
F_auto_run remove2
fi
fi
return 0
;;
esac
F_terminal_show "${tYEL}===== Router reboot notification enable/disable =====${tCLR}"
if [ "$status_email_cfg" = 1 ] && [ "$user_reboot_notification" = 0 ] ; then
F_notify_reboot create
elif [ "$user_reboot_notification" = 1 ] ; then
F_notify_reboot remove
else
F_terminal_padding
F_terminal_check_fail "Error - invalid Email settings, use Main Menu to add settings"
fi
F_menu_exit
} # notify_reboot
F_notify_update() {
case "$1" in
'check')
status_update=0
[ "$status_email_cfg" = 1 ] && [ "$user_update_notification" = 1 ] && \
[ "$status_cru" = 1 ] && [ "$status_srvstrt" = 1 ] && status_update=1 && return 0
return 1
;;
'create')
F_auto_run create2
F_replace_var update_cron_epoch 0 "$update_src"
F_replace_var user_update_notification 1 "$config_src"
user_update_notification=1
F_log_terminal_ok "Enabled script update Email notification"
return 0
;;
'remove')
if [ "$user_wanip_notification" = 0 ] && [ "$user_fw_update_notification" = 0 ] && [ "$user_reboot_notification" = 0 ] && [ "$user_wanip_monitor" = 0 ] ; then
F_auto_run remove2
fi
F_replace_var user_update_notification 0 "$config_src"
user_update_notification=0
F_log_terminal_ok "Disabled script update Email notification"
return 0
;;
esac
F_terminal_show "${tYEL}===== Script update notification enable/disable =====${tCLR}"
if [ "$status_email_cfg" = 1 ] && [ "$user_update_notification" = 0 ] ; then
F_notify_update create
elif [ "$user_update_notification" = 1 ] ; then
F_notify_update remove
else
F_terminal_padding
F_terminal_check_fail "Error - invalid Email settings, use Main Menu to edit settings"
fi
F_menu_exit
} # notify_update
F_notify_wanip() {
case "$1" in
'check')
status_wanip=0
if [ "$status_email_cfg" = 1 ] && [ "$user_wanip_notification" = 1 ] && [ "$status_cru" = 1 ] && [ "$status_srvstrt" = 1 ] && [ "$user_wanip_monitor" = 1 ] ; then
[ "$fw_sw_mode" = 1 ] && [ "$status_wanevent" = 0 ] && return 1
status_wanip=1
return 0
fi
return 1
;;
'create')
F_replace_var user_wanip_notification 1 "$config_src"
! F_wanip_monitor check && F_wanip_monitor create
F_log_terminal_ok "Enabled WAN IP change Email notification"
user_wanip_notification=1
return 0
;;
'remove')
if [ "$2" != 'nouser' ] ; then
F_terminal_header
[ "$2" = 'mon' ] && F_terminal_show "${tYEL}===== WAN IP change monitor enable/disable =====${tCLR}" && F_terminal_padding
F_terminal_warning
F_terminal_show "This will disable WAN IP change Email notification"
F_terminal_show "You will not receive an Email notification if your WAN IP changes."
if F_confirm "Are you sure you wish to disable?" ; then
F_terminal_check_ok "Ok received, disabling..."
F_replace_var user_wanip_notification 0 "$config_src"
user_wanip_notification=0
F_log_terminal_ok "Disabled WAN IP Email notification"
return 0
else
F_terminal_check_ok "No received, exiting..."
return 1
fi
else
F_replace_var user_wanip_notification 0 "$config_src"
user_wanip_notification=0
F_log_terminal_ok "Disabled WAN IP change Email notfication"
return 0
fi
;;
esac
F_terminal_show "${tYEL}===== WAN IP change notification enable/disable =====${tCLR}"
if [ "$status_email_cfg" = 1 ] && [ "$user_wanip_notification" = 0 ] ; then
if [ "$dual_wan_check" = 1 ] && [ "$(F_nvram wans_dualwan)" != 'wan none' ] ; then
F_log_terminal_fail "Error - Dual WAN is enabled, WAN IP change cannot be enabled"
F_menu_exit
fi
F_notify_wanip create
elif [ "$user_wanip_notification" = 1 ] ; then
F_notify_wanip remove
else
F_terminal_padding
F_terminal_check_fail "Error - invalid Email settings, use Main Menu to add settings"
fi
F_menu_exit
} # notify_wanip
F_wanip_monitor() {
case "$1" in
'check')
status_wanipmon=0
if [ "$user_wanip_monitor" = 1 ] && [ "$status_cru" = 1 ] && [ "$status_srvstrt" = 1 ] ; then
[ "$fw_sw_mode" = 1 ] && [ "$status_wanevent" = 0 ] && return 1
status_wanipmon=1
return 0
fi
return 1
;;
'create')
building_settings=1
F_auto_run createall
! F_compare && F_script_wan_update
F_replace_var user_wanip_monitor 1 "$config_src"
F_log_terminal_ok "Enabled WAN IP change monitoring"
return 0
;;
'remove')
user_wanip_monitor=0
if [ "$user_wanip_notification" = 1 ] ; then
if ! F_notify_wanip remove mon ; then
F_terminal_check_fail "Disabling cancelled"
F_menu_exit
fi
fi
F_replace_var user_wanip_monitor 0 "$config_src"
[ "$2" != 'un' ] && F_log_terminal_ok "Disabled WAN IP change monitoring"
if [ "$user_wanip_notification" = 0 ] && [ "$user_fw_update_notification" = 0 ] && [ "$user_update_notification" = 0 ] && [ "$user_reboot_notification" = 0 ] ; then
[ "$2" != 'un' ] && F_auto_run removeall
else
if [ "$fw_sw_mode" = 1 ]
then F_wan_event remove
else F_terminal_check_ok "Not in router mode, skipping wan-event removal"
fi
fi
if [ -n "$user_custom_script" ] ; then
F_terminal_check_ok "Removed WAN IP change custom script entry"
F_opt_script remove
fi
return 0
;;
esac
F_terminal_show "${tYEL}===== WAN IP change monitor enable/disable =====${tCLR}"
if [ "$user_wanip_monitor" = 0 ]
then F_wanip_monitor create
else F_wanip_monitor remove
fi
}
# BUILD USER SETTINGS FUNCTIONS #######################################################################################
#######################################################################################################################
# all user entry functions called by until loops and return 1 for failed input and restart or return 0 with completed Y in while loop
F_send_to_addr() {
F_terminal_entry_header 1
F_terminal_show "Enter the Email address you wish to send a notification Email"
F_terminal_show "to when your WAN IP changes"
F_terminal_show "eg. ${tGRN}myrecipient@myemail.com${tCLR}"
[ -n "$user_send_to_addr" ] && F_terminal_padding && printf "%b Currently set to : %b%s%b \n" "$tTERMHASH" "$tGRN" "$user_send_to_addr" "$tCLR" && F_terminal_show "Leave entry blank to keep current"
F_terminal_padding ; F_terminal_entry "Send to address : "
read -r send_to_entry
[ -z "$user_send_to_addr" ] && [ -z "$send_to_entry" ] && F_terminal_check_fail "Error, Email send to address cannot be empty - Any key to retry" && read -rsn1 && return 1
[ -z "$send_to_entry" ] && [ -n "$user_send_to_addr" ] && return 0
case "$send_to_entry" in
E|e) F_menu_exit ;;
esac
if F_confirm correct "$send_to_entry" ; then
F_replace_var user_send_to_addr "$send_to_entry" "$config_src"
user_send_to_addr="$send_to_entry"
else
send_to_entry=''
return 1
fi
} ### send_to_addr
F_send_to_cc() {
if [ -n "$user_send_to_cc" ] ; then
F_terminal_entry_header 2
printf "%b Second Email recipient already set to : %b%s%b \n\n" "$tTERMHASH" "$tGRN" "$user_send_to_cc" "$tCLR" ; F_terminal_padding
while true; do
F_terminal_check "Y||y keep - N||n enter new - R||r remove current & skip to server entry" # for edits can remove 2nd email if wanted.
read -rsn 1 ccmailwait2
case "$ccmailwait2" in
Y|y) return 0 ;;
N|n) user_send_to_cc= ; return 1 ;;
R|r) F_replace_var user_send_to_cc "" "$config_src" && user_send_to_cc= && return 0 ;;
E|e) F_menu_exit ;;
*) F_terminal_check_fail "Invalid Entry , Y||y N||n R||r - Any key to retry" ; read -rsn1 ; F_terminal_erase ; continue ;;
esac
break
done
else
F_terminal_entry_header 2
F_terminal_show "Enter a 2nd Email address you wish to send a notification Email"
F_terminal_show "to when your WAN IP changes"
F_terminal_show "eg. ${tGRN}my2ndrecipient@myemail.com${tCLR}"
F_terminal_padding ; F_terminal_show "Leave entry blank to leave CC option empty and continue"
F_terminal_padding ; F_terminal_entry "Send to CC address : "
read -r send_to_cc_entry
[ -z "$send_to_cc_entry" ] && return 0
case "$send_to_cc_entry" in
E|e) F_menu_exit ;;
esac
if F_confirm correct "$send_to_cc_entry" ; then
F_replace_var user_send_to_cc "$send_to_cc_entry" "$config_src"
user_send_to_cc="$send_to_cc_entry"
else
user_send_to_cc=''
return 1
fi
fi
} ### send_to_cc
F_smtp_server() {
F_terminal_entry_header 3
F_terminal_show "Enter the SMTP server address and port # like as shown for your"
F_terminal_show "Email provider - eg. ${tGRN}smtp.myemailprovider.com:465${tCLR}"
[ -n "$user_smtp_server" ] && F_terminal_padding && printf "%b Currently set to : %b%s%b\n" "$tTERMHASH" "$tGRN" "$user_smtp_server" "$tCLR" && F_terminal_show "Leave entry blank to keep current"
F_terminal_padding ; F_terminal_entry "Server address and port : "
read -r smtp_server_entry
[ -z "$user_smtp_server" ] && [ -z "$smtp_server_entry" ] && F_terminal_check_fail "Error, Server address cannot be empty - Any key to retry" && read -rsn1 && return 1
[ -z "$smtp_server_entry" ] && [ -n "$user_smtp_server" ] && return 0
case "$smtp_server_entry" in
E|e) F_menu_exit ;;
esac
if F_confirm correct "$smtp_server_entry" ; then
F_replace_var user_smtp_server "$smtp_server_entry" "$config_src"
user_smtp_server="$smtp_server_entry"
else
smtp_server_entry=''
return 1
fi
} ### smtp_server
F_send_type() {
F_terminal_entry_header 4
F_terminal_show "SMTP Email server send configuration type for ${tGRN}${user_smtp_server}${tCLR}"
F_terminal_padding
F_terminal_show " ${tYEL}Selection${tCLR}"
F_terminal_show "WITH password and SSL required (default) - 1"
F_terminal_show "WITH password and StartTLS - 2"
F_terminal_show "ISP type with NO password and NO StartTLS/SSL- eg.port 25 - 3"
F_terminal_show "WITH password and NO StartTLS or SSL (plain auth) - 4"
F_terminal_show "WITH password and StartTLS v1 - 5"
[ -n "$user_message_type" ] && F_terminal_padding && printf "%b Currently set to : %b%s%b\n" "$tTERMHASH" "$tGRN" "$user_message_type" "$tCLR" && F_terminal_show "Leave selection blank to keep current setting"
F_terminal_padding ; F_terminal_entry "Selection : "
read -r send_type_entry
case "$send_type_entry" in
1|2|3|4|5) ;;
"") if [ -n "$user_message_type" ] ; then
return 0
else
F_terminal_check_fail "Invalid entry, 1,2,3,4,5 only - Any key to retry" && read -rsn1 && return 1
fi
;;
e|E) F_menu_exit ;;
*) F_terminal_check_fail "Invalid Entry, 1,2,3,4,5 only - Any key to retry" && read -rsn1 && return 1 ;;
esac
if ! F_confirm correct "$send_type_entry" ; then
send_type_entry=''
return 1
fi
[ "$send_type_entry" = "1" ] && F_replace_var user_message_type "smtp_ssl" "$config_src" && user_message_type="smtp_ssl"
[ "$send_type_entry" = "2" ] && F_replace_var user_message_type "smtp_start_tls" "$config_src" && user_message_type="smtp_start_tls"
[ "$send_type_entry" = "3" ] && F_replace_var user_message_type "smtp_isp_nopswd" "$config_src" && user_message_type="smtp_isp_nopswd"
[ "$send_type_entry" = "4" ] && F_replace_var user_message_type "smtp_plain_auth" "$config_src" && user_message_type="smtp_plain_auth"
[ "$send_type_entry" = "5" ] && F_replace_var user_message_type "smtp_start_tls_v1" "$config_src" && user_message_type="smtp_start_tls_v1"
if [ "$user_message_type" != 'smtp_isp_nopswd' ] && [ "$user_message_type" != 'smtp_plain_auth' ] ; then
F_terminal_header ; F_terminal_warning
F_terminal_show "If using GMail for your sending service you must have"
F_terminal_show "2 factor authentication enabled and create a App"
F_terminal_show "password for this script to use"
F_terminal_padding ; F_terminal_check "Any key to continue" && read -rsn1
fi
return 0
} ### send_type
F_login_addr() {
F_terminal_entry_header 5
F_terminal_show "Enter the Email login address (username) for your Email provider"
F_terminal_show "eg. ${tGRN}myemail@myemailprovider.com${tCLR} for ${tGRN}${user_smtp_server}${tCLR}"
if [ -n "$user_login_addr" ] ; then
F_terminal_padding
F_terminal_show "Currently set to : ${tGRN}${user_login_addr}${tCLR}"
F_terminal_show "Leave entry blank to keep current"
fi
F_terminal_padding
F_terminal_entry "Login Email addr : "
read -r email_login_entry
[ -z "$user_login_addr" ] && [ -z "$email_login_entry" ] && F_terminal_check_fail "Error - login credentials cannot be empty - Any key to retry" && read -rsn1 && return 1
[ -z "$email_login_entry" ] && [ -n "$user_login_addr" ] && return 0
case "$email_login_entry" in
E|e) F_menu_exit ;;
esac
if F_confirm correct "$email_login_entry" ; then
F_replace_var user_login_addr "$email_login_entry" "$config_src"
F_replace_var user_from_addr "$email_login_entry" "$config_src"
user_login_addr="$email_login_entry"
user_from_addr="$email_login_entry"
else
email_login_entry=''
return 1
fi
} ### from_email_addr
F_from_addr() {
F_terminal_entry_header 6
F_terminal_show "Enter the message 'from' Email address for the notification Email"
F_terminal_show "Typically this is the same as your Email login address"
F_terminal_padding
F_terminal_show "Currently set to : ${tGRN}${user_from_addr}${tCLR}"
F_terminal_show "Leave entry blank to keep current"
F_terminal_padding
F_terminal_entry "Email from address : "
read -r from_addr_entry
[ -z "$user_from_addr" ] && [ -z "$from_addr_entry" ] && F_terminal_show "Error, cannot be blank, any key to retry" && read -rsn1 && return 1
case "$from_addr_entry" in
E|e) F_menu_exit ;;
esac
F_terminal_padding
if [ -n "$user_from_addr" ] && [ -z "$from_addr_entry" ] ; then
return 0
fi
if F_confirm correct "$from_addr_entry" ; then
F_replace_var user_from_addr "$from_addr_entry" "$config_src"
[ -n "$from_addr_entry" ] && user_from_addr="$from_addr_entry"
else
from_addr_entry=''
return 1
fi
} # from_addr
F_email_from() {
F_terminal_entry_header 7
F_terminal_show "Enter the Email message 'from' name you'd like to appear"
if [ -n "$user_email_from" ] ; then
F_terminal_padding
F_terminal_show "Currently set to : ${tGRN}${user_email_from}${tCLR}"
F_terminal_show "Leave entry blank to keep current"
fi
F_terminal_padding
F_terminal_entry "Email from name : "
read -r email_from_entry
[ -z "$user_email_from" ] && [ -z "$email_from_entry" ] && F_terminal_check_fail "Error - from name cannot be empty - Any key to retry" && read -rsn1 && return 1
[ -z "$email_from_entry" ] && [ -n "$user_email_from" ] && return 0
case "$email_from_entry" in
E|e) F_menu_exit ;;
esac
F_terminal_padding
if F_confirm correct "$email_from_entry" ; then
F_replace_var user_email_from "$email_from_entry" "$config_src"
user_email_from="$email_from_entry"
else
email_from_entry=''
return 1
fi
} # email_from
F_email_to_name() {
F_terminal_entry_header 8
F_terminal_show "Enter the Email message 'send to' name you'd like to appear"
if [ -n "$user_msg_to" ] ; then
F_terminal_padding
F_terminal_show "Currently set to : ${tGRN}${user_msg_to}${tCLR}"
F_terminal_show "Leave entry blank to keep current"
fi
F_terminal_padding
F_terminal_entry "Email to name : "
read -r email_to_entry
[ -z "$user_msg_to" ] && [ -z "$email_to_entry" ] && F_terminal_check_fail "Error - from name cannot be empty - Any key to retry" && read -rsn1 && return 1
[ -z "$email_to_entry" ] && [ -n "$user_msg_to" ] && return 0
case "$email_to_entry" in
E|e) F_menu_exit ;;
esac
F_terminal_padding
if F_confirm correct "$email_to_entry" ; then
F_replace_var user_msg_to "$email_to_entry" "$config_src"
user_msg_to="$email_to_entry"
else
email_to_entry=''
return 1
fi
} # email_to_name
F_pswd_entry() {
old_ifs=$IFS
charcount=1
while IFS= read -rsn1 char ; do # -s or terminal will leave last char, easier this way
if [ -z "$char" ] ; then # enter hit
[ "$charcount" -eq 1 ] && printf '\n' || printf '\b*\n'
break
fi
if [ "$char" = $'\x7f' ] || [ "$char" = $'\x08' ] ; then # backspace
if [ "$charcount" != '1' ] ; then
passwordentry="${passwordentry%?}"
printf '\b \b'
charcount=$((charcount - 1))
fi
else
if [ "$charcount" = '1' ] ; then # first char
printf "%s" "$char"
passwordentry="$char"
else
printf "\b*%s" "$char" # terminal output
passwordentry="${passwordentry}$char" # create var
fi
charcount=$((charcount + 1))
fi
done
IFS=$old_ifs
} # pswd_entry replaces typed chars with *
F_smtp_pswd() {
F_terminal_entry_header 8
F_terminal_show "${tYEL}===== Password entry menu =====${tCLR} E||e to exit"
F_terminal_padding
if [ "$amtm_import" = 1 ] && [ "$status_amtm" = 1 ] ; then
F_terminal_check_ok "amtm import ${tGRN}enabled${tCLR} using its saved password"
F_terminal_padding
F_terminal_check "S||s to show amtm password - Any key to exit..."
read -rsn1 pswdamtm
case "$pswdamtm" in
S|s)
user_pswd="$(eval "$(F_printfstr "$amtm_d" | openssl base64 -d)" < "$amtm_cred_loc")"
F_terminal_check_ok "Saved amtm password : $(F_printfstr "$user_pswd")"
user_pswd=
F_menu_exit
;;
esac
F_clean_exit reload
elif [ -f "$cred_loc" ] ; then
F_terminal_check_ok "Saved password exists, leave blank to use saved - S||s to show password"
fi
if [ "$status_email_cfg" = 0 ] || [ "$user_smtp_server" = 'smtp_isp_nopswd' ] && [ "$building_settings" = 0 ] ; then
F_terminal_check_fail "Error, Email settings not created or smtp type is smtp_no_pswd"
F_terminal_padding
F_terminal_check "Any key to return to the main menu"
read -rsn1
F_clean_exit reload
fi
F_terminal_show "Enter the password for your Email"
F_terminal_padding
F_terminal_entry "Password : "
F_pswd_entry
password_entry_1="$passwordentry"
case "$passwordentry" in
E|e)
F_terminal_check_ok "Exit confirmed"
F_menu_exit
;;
S|s)
F_terminal_padding
if [ -f "$cred_loc" ] ; then
user_pswd="$(eval "$(F_printfstr "$user_d" | openssl base64 -d)" < "$cred_loc")"
F_terminal_check_ok "Saved password : $(F_printfstr "$user_pswd")"
user_pswd=
else
F_terminal_check_fail "No password to show"
fi
F_menu_exit
;;
esac
if [ -f "$cred_loc" ] && [ -z "$passwordentry" ] ; then # keep saved
F_terminal_erase
F_terminal_check_ok "Keeping saved"
return 0
elif [ ! -f "$cred_loc" ] && [ -z "$passwordentry" ] ; then
F_terminal_show "Error - Password cannot be empty - Any key to retry - E||e to Exit"
read -rsn1 waitsmtppswd
case "$waitsmtppswd" in
E|e) F_clean_exit reload ;;
esac
return 1
fi
passwordentry=''
F_terminal_entry "Reconfirm : "
F_pswd_entry
password_entry_2="$passwordentry"
case "$passwordentry" in
E|e) F_menu_exit ;;
esac
if [ "$password_entry_1" != "$password_entry_2" ] || [ -z "$password_entry_2" ] ; then
F_terminal_check_fail "Passwords do NOT match - Any key to retry"
read -rsn1
password_entry_1='' ; password_entry_2='' ; passwordentry=''
return 1
fi
# encrypt remove new lines so no sed errors
user_pswd_enc="$(F_printfstr "$password_entry_1" | eval "$(F_printfstr "$user_e" | openssl base64 -d)" )"
if F_printfstr "$user_pswd_enc" > "$cred_loc" ; then
F_chmod "$cred_loc"
F_terminal_check_ok "Password successfully encrypted and saved"
passwordentry='' ; password_entry_1='' ; password_entry_2='' ; user_pswd_enc=''
return 0
else
F_terminal_show "Failed updating script with encrypted password"
passwordentry='' ; password_entry_1='' ; password_entry_2='' ; user_pswd_enc=''
return 0
fi
} # smtp_pswd
F_build_settings() {
building_settings=1 # for opt_sample no exit, move to test option
until F_send_to_addr ; do : ; done
until F_send_to_cc; do : ; done
until F_smtp_server ; do : ; done
until F_send_type ; do : ; done
until F_login_addr ; do : ; done
until F_from_addr ; do : ; done
until F_email_from ; do : ; done
until F_email_to_name ; do : ; done
[ "$user_message_type" != 'smtp_isp_nopswd' ] && until F_smtp_pswd ; do : ; done
F_replace_var created_date "$(F_date f)" "$config_src"
created_date="$(F_date f)"
F_terminal_header
F_status | sed -n '/Current saved WAN/,/Script install date/p'
F_terminal_check "Any key to continue to view sample Email output"
read -rsn1
source "$config_src"
F_settings_test
F_opt_sample
F_terminal_padding
F_log_terminal_ok "Congratulations, you've completed the wicens setup"
F_terminal_padding
F_terminal_check "Hit T|t to send a test Email - M|m for Main Menu - Any key to exit"
read -rsn1 setupwait
case "$setupwait" in
T|t) F_opt_test ; F_menu_exit ;;
M|m) F_clean_exit reload ;;
*)
printf "\r%b" "$tERASE"
F_terminal_check_ok "This script is now configured"
F_terminal_show "Run wicens on the command line to run script manually with set config"
F_clean_exit
;;
esac
} # build_settings
F_edit_settings() {
F_terminal_header
F_terminal_show "${tYEL}===== Welcome to the wicens Email config editor =====${tCLR} E||e to exit"
F_terminal_padding
if [ "$amtm_import" = 1 ] ; then
F_terminal_check_fail "amtm import currently enabled, edit menu unavailable"
F_terminal_padding
F_terminal_show "Edit amtm Email settings within amtm"
F_terminal_show "To edit wicens saved Email settings disable amtm import"
F_terminal_padding
F_terminal_check "Any key to return to the main menu"
read -rsn1
F_clean_exit reload
fi
F_terminal_show " ${tYEL}Setting Select Setting${tCLR}"
F_edit "Current Email send to address 1 " "$user_send_to_addr"
F_edit "Current Email send to CC address 2 " "$user_send_to_cc"
F_edit "Current Email server addr:port 3 " "$user_smtp_server"
F_edit "Current Email send format type 4 " "$user_message_type"
F_edit "Current Email login user (address) 5 " "$user_login_addr"
F_edit "Current Email from Email address 6 " "$user_from_addr"
F_edit "Current Email message from name 7 " "$user_email_from"
F_edit "Current Email message to name 8 " "$user_msg_to"
[ "$user_message_type" = "smtp_ssl" ] && F_edit "Current curl SSL protocol 9 " "$protocol"
[ -f "$cred_loc" ] && F_edit "Email Password menu 0 " "Password saved"
F_terminal_show "Reset saved Email settings R||r "
F_terminal_padding
F_terminal_show "Make a selection or E||e to exit"
F_terminal_padding
while true; do
F_terminal_check "Selection : "
read -r editselect
case "$editselect" in
1) until F_send_to_addr ; do : ; done ;;
2) until F_send_to_cc; do : ; done ;;
3) until F_smtp_server ; do : ; done ;;
4) until F_send_type ; do : ; done ;;
5) until F_login_addr ; do : ; done ;;
6) until F_from_addr ; do : ; done ;;
7) until F_email_from ; do : ; done ;;
8) until F_email_to_name ; do : ; done ;;
9)
if [ "$user_message_type" = "smtp_ssl" ] ; then
if [ "$protocol" = 'smtps' ] ; then
F_replace_var protocol 'smtp' "$config_src"
F_terminal_padding ; F_terminal_check_ok "Switched to protocol SMTP" ; F_terminal_padding
else
F_replace_var protocol 'smtps' "$config_src"
F_terminal_padding ; F_terminal_check_ok "Switched to protocol SMTPS" ; F_terminal_padding
fi
else
F_terminal_erase
F_fail_entry
fi
F_terminal_check "Any key to return..."
read -rsn1
;;
0) if F_ready_check pswdset ; then
until F_smtp_pswd ; do : ; done
F_menu_exit
fi
;;
R|r)
F_terminal_erase
F_terminal_warning
F_terminal_show "This will remove all saved Email settings, custom text/subject/script,"
F_terminal_show "and set all notification options to disabled"
if F_confirm "Reset settings?" ; then
[ "$status_amtm" = 1 ] && F_amtm remove
F_replace_var created_date '' "$config_src"
for remove_config in user_send_to_addr user_send_to_cc user_smtp_server user_from_addr user_message_type user_login_addr user_from_addr # userfromname is temp
do
[ -n "$remove_config" ] && F_replace_var "$remove_config" '' "$config_src"
done
[ -n "$user_custom_script" ] && F_replace_var 'user_custom_script' '' "$config_src"
[ -n "$user_custom_subject" ] && F_replace_var 'user_custom_subject' '' "$config_src"
[ -n "$user_custom_text" ] && F_replace_var 'user_custom_text' '' "$config_src"
F_log_terminal_ok "User settings in config file reset"
[ -f "$cred_loc" ] && rm -f "$cred_loc" && F_log_terminal_ok "Removed saved password"
F_replace_var user_email_from 'wicens script' "$config_src"
F_auto_run removeall
[ "$user_reboot_notification" = 1 ] && F_notify_reboot remove un
[ "$user_fw_update_notification" = 1 ] && F_notify_firmware remove un
[ "$user_update_notification" = 1 ] && F_notify_update remove un
[ "$user_wanip_notification" = 1 ] && F_notify_wanip remove nouser > /dev/null 2>&1
F_replace_var created_date '' "$config_src"
F_log_terminal_ok "Script Email settings reset"
F_terminal_check "Any key to continue..."
read -rsn1
F_clean_exit reset
else
F_terminal_check_ok "No, selected"
F_menu_exit
fi
;;
E|e) F_clean_exit reload ;;
*) F_terminal_erase && F_fail_entry ;;
esac
break
done
F_edit_settings
} # edit_settings
F_amtm() {
case "$1" in
'check')
if [ ! -f "$amtm_email_conf" ] || [ ! -f "$amtm_cred_loc" ] ; then
return 1
else
for var_set_check in FROM_ADDRESS TO_NAME TO_ADDRESS FROM_ADDRESS USERNAME SMTP PORT PROTOCOL ; do
pull_var=$(grep -F "$var_set_check" "$amtm_email_conf" | cut -d'=' -f2 | tr -d '"')
[ -z "$pull_var" ] && return 1
done
fi
return 0
;;
'create')
building_settings=1
F_replace_var amtm_import 1 "$config_src"
F_replace_var created_date "$(F_date f)" "$config_src"
F_log_terminal_ok "amtm Email settings enabled"
F_amtm load
building_settings=0
return 0
;;
'load')
source "$amtm_email_conf"
user_send_to_addr="$TO_ADDRESS"
user_login_addr="$USERNAME"
user_from_addr="$FROM_ADDRESS"
user_smtp_server="${SMTP}:${PORT}"
user_message_type='smtp_ssl'
protocol="$PROTOCOL"
ssl_flag="$SSL_FLAG"
return 0
;;
'remove')
F_replace_var amtm_import 0 "$config_src"
F_log_terminal_ok "amtm Email settings disabled"
F_user_settings
F_replace_var created_date '' "$config_src" # set created date blank
[ "$status_email_cfg" = 1 ] && F_replace_var created_date "$(F_date f)" "$config_src" # script has saved settings that are good
return 0
;;
esac
F_terminal_show "${tYEL}===== amtm Email config sync enable/disable =====${tCLR}"
if [ "$status_amtm" = 1 ] && [ "$amtm_import" = 0 ] ; then
F_amtm create
elif [ "$amtm_import" = 1 ] ; then
F_amtm remove
else
F_terminal_check_fail "Cannot enable, amtm settings invalid"
fi
F_menu_exit
} # amtm
# NOTIFICATIONS #######################################################################################################
#######################################################################################################################
F_email_eg() {
sample_email=1
F_terminal_header
F_terminal_show "${tYEL}===== wicens Email instructions =====${tCLR} E||e to exit"
F_terminal_padding
F_terminal_show "Your script should create the text file containing the information below."
F_terminal_show "For plain text Email only, please research how to implement HTML if needed"
F_printf "$tGRN"
F_printf "From: \"${user_email_from}\" <${user_from_addr}> ${tPUR}*from address set in wicens/amtm${tGRN}"
F_printf "To: \"${user_msg_to}\" <${user_send_to_addr}> ${tPUR}*or custom To: Email address passed on start${tGRN}"
F_printfstr "Subject: Place your subject text here"
F_printf "Date: $(date -R) ${tPUR}*Current date/time in RFC format use date -R command${tGRN}"
F_printf "${tPUR} *this space is required between Email header info and body text${tGRN}"
# body
F_printfstr "Hello world!"
F_printfstr "This is my custom Email body text"
F_email_seperator
F_printfstr "Message sent: $(F_date f)"
F_printfstr "Script ran with option : ${run_option}"
F_printf "A message from wicens script v${script_version} on your ${fw_device_model}${tCLR}"
F_terminal_show "End of Email content"
sample_email=0
F_menu_exit
} # email_eg
F_fw_update_email_msg() {
if [ "$sample_email" = 0 ] ; then
new_fw_ver="$(F_nvram webs_state_info)"
new_fw_ver_pretty="$(F_printfstr "$new_fw_ver" | awk -F '_' '{print $2 "." $3 "_" $4}')"
F_log_terminal_ok "Sending Email notification for available firmware update - v${new_fw_ver_pretty}"
fi
[ -f "$fw_email" ] && rm -f "$fw_email"
mail_file="$fw_email"
{
# header
F_printfstr "From: \"${user_email_from}\" <${user_from_addr}>"
F_printfstr "To: \"${user_msg_to}\" <${user_send_to_addr}>"
[ -n "$user_send_to_cc" ] && F_printfstr "Cc: ${user_send_to_cc}"
if [ -z "$user_custom_subject_decoded_f" ]
then F_printfstr "Subject: ${firmware_subject}"
else F_printfstr "Subject: ${user_custom_subject_decoded_f}"
fi
F_printfstr "Date: $(F_date r)"
# mime html
if [ "$sample_email" = 0 ] ; then
F_printfstr 'MIME-Version: 1.0'
F_printfstr 'Content-Type: text/html; charset="UTF-8"'
F_printfstr ''
F_printfstr ''
F_printfstr ''
F_printfstr ''
else
F_terminal_padding
fi
# body
if [ "$test_mode" = 1 ] && [ "$sample_email" = 0 ] ; then
F_printfp "########## TEST message ##########"
else
F_printfp "********** NOTICE **********"
fi
F_printfp "A newer firmware version is available for ASUS router"
F_email_seperator
F_printfpre "Model : ${fw_device_model}"
F_printfpre "Host/Domain : ${fw_pulled_device_name}.${fw_pulled_lan_name}"
F_printfpre "LAN IP : ${fw_lan_addr}"
F_printfp "Installed fw version : ${fw_build_full}"
F_printfp "Available fw version : ${new_fw_ver_pretty}"
F_printfp "Visit https://www.asuswrt-merlin.net"
[ -n "$user_custom_text_f" ] && F_email_seperator && F_printfpre "$(F_printf "${user_custom_text_f_decoded}")"
F_email_seperator
F_printfp "Message sent: $(F_date f)"
F_printfp "Script ran with option : ${run_option}"
F_printfp "A message from wicens script v${script_version}"
# html footer
F_printfstr ''
F_printfstr ''
} > "$fw_email"
[ "$sample_email" = 1 ] && return 0
###########################################################################
if [ -f "$wicens_fw_retry" ] ; then
F_printfstr "Attempting to send script fw update notification $(F_date r)" >> "$wicens_fw_retry"
elif [ "$test_mode" = 0 ] ; then
{
F_printfstr "#!/bin/sh"
F_printfstr "wicens_fw_retry_time=${run_epoch}"
F_printfstr "# Attempting to send firmware update notification $(F_date r)"
} > "$wicens_fw_retry"
F_chmod "$wicens_fw_retry"
fi
F_internet_check fwupdate
if ! F_send_email; then
F_log_terminal_fail "Error, failed to send firmware update Email notification"
user_pswd=''
rm -f "$fw_email"
cat "$mail_log" >> "$script_log_loc"
return 1
fi
user_pswd=''
rm -f "$fw_email"
rm -f "$wicens_fw_retry" 2> /dev/null # remove cron retry file
F_log_terminal_ok "Finished sending firmware update Email notification"
F_replace_var fw_notify_state 0 "$update_src" # set 1 by caller, set 0 on success
return 0
} # fw_update_email_msg
F_script_update_email_msg() {
[ -f "$update_email" ] && rm -f "$update_email"
mail_file="$update_email"
{
# header
F_printfstr "From: \"${user_email_from}\" <${user_from_addr}>"
F_printfstr "To: \"${user_msg_to}\" <${user_send_to_addr}>"
[ -n "$user_send_to_cc" ] && F_printfstr "Cc: ${user_send_to_cc}"
if [ -z "$user_custom_subject_decoded_s" ]
then F_printfstr "Subject: ${script_subject}"
else F_printfstr "Subject: ${user_custom_subject_decoded_s}"
fi
F_printfstr "Date: $(F_date r)"
# mime html
F_printfstr 'MIME-Version: 1.0'
F_printfstr 'Content-Type: text/html; charset="UTF-8"'
F_printfstr ''
F_printfstr ''
F_printfstr ''
F_printfstr ''
# body
F_printfp "********** NOTICE **********"
F_printfp "Update is available for wicens script"
F_email_seperator
F_printfpre "Model : ${fw_device_model}"
F_printfpre "Host/Domain : ${fw_pulled_device_name}.${fw_pulled_lan_name}"
F_printfpre "LAN IP : ${fw_lan_addr}"
F_email_seperator
case "$update_avail" in
'hotfix')
F_printfp "A hotfix is available for v${script_version} of wicens"
F_email_seperator # -----
F_printfp "Change log :"
F_printfpre "$(/usr/sbin/curl -fsL --retry 3 --connect-timeout 5 "https://raw.githubusercontent.com/maverickcdn/wicens/master/CHANGELOG.md" | /bin/sed -n "/^## $script_version/,/^##/p" | head -n -1 | /bin/sed 's/## //')
"
;;
*)
F_printfpre "Version : ${update_avail} is available"
F_email_seperator # -----
F_printfp "Change log :"
F_printfpre "$(/usr/sbin/curl -fsL --retry 3 --connect-timeout 5 "https://raw.githubusercontent.com/maverickcdn/wicens/master/CHANGELOG.md" | /bin/sed -n "/^## $git_version/,/^## $script_version/p" | head -n -1 | /bin/sed 's/## //')
"
;;
esac
F_printfp "Run wicens script on your router and select option I||i to update"
[ -n "$user_custom_text_s" ] && F_email_seperator && F_printfpre "$(F_printf "${user_custom_text_s_decoded}")"
F_email_seperator # -----
F_printfp "Message sent: $(F_date f)"
F_printfp "Script ran with option : ${run_option}"
F_printfp "A message from wicens script v${script_version}"
# html footer
F_printfstr ''
F_printfstr ''
} > "$update_email"
[ "$sample_email" = 1 ] && return 0
###########################################################################
if ! F_send_email; then
F_log_terminal_fail "Error, failed to send update Email notification"
user_pswd=''
rm -f "$update_email"
cat "$mail_log" >> "$script_log_loc"
return 1 # skip below hopefully resend next cron if message fail
fi
user_pswd=''
rm -f "$update_email"
rm -f "$wicens_update_retry"
F_log_terminal_ok "Finished sending update Email notification"
F_replace_var update_notify_state 1 "$update_src"
return 0
} # script_update_email_msg
F_reboot_email_msg() {
router_reboot_downtime="$(($(F_date s) - router_reboot_downtime))" # time between last saved record and reboot call = 'downtime'
[ -f "$reboot_email" ] && rm -f "$reboot_email"
mail_file="$reboot_email"
F_uptime
if [ "$sample_email" = 0 ] || [ "$test_mode" = 0 ] ; then
if [ ! -f '/tmp/wicens_reboot_uptime.tmp' ] ; then # keep original found uptime for failed email retries
F_printfstr "$router_reboot_uptime" > /tmp/wicens_reboot_uptime.tmp
F_printfstr "$router_reboot_downtime" > /tmp/wicens_reboot_downtime.tmp
else
router_reboot_uptime="$(cat '/tmp/wicens_reboot_uptime.tmp')" # were in a Email retry use initial saved
router_reboot_downtime="$(cat '/tmp/wicens_reboot_downtime.tmp')"
fi
[ "$sample_email" = 0 ] && [ "$router_uptime" -lt 7200 ] && sleep "$reboot_notify_wait" # sleep only for services-start call (not testing)
[ "$sample_email" = 0 ] && F_log_terminal_ok "Sending router reboot notification to ${user_send_to_addr}"
else
router_reboot_downtime=0
router_reboot_uptime="$router_uptime"
fi
{
# header
F_printfstr "From: \"${user_email_from}\" <${user_from_addr}>"
F_printfstr "To: \"${user_msg_to}\" <${user_send_to_addr}>"
[ -n "$user_send_to_cc" ] && F_printfstr "Cc: ${user_send_to_cc}"
if [ -z "$user_custom_subject_decoded_r" ]
then F_printfstr "Subject: ${reboot_subject}"
else F_printfstr "Subject: ${user_custom_subject_decoded_r}"
fi
F_printfstr "Date: $(F_date r)"
# mime html
if [ "$sample_email" = 0 ] ; then
# mime html
F_printfstr 'MIME-Version: 1.0'
F_printfstr 'Content-Type: text/html; charset="UTF-8"'
F_printfstr ''
F_printfstr ''
F_printfstr ''
F_printfstr ''
else
F_terminal_padding
fi
# body
if [ "$test_mode" = 1 ] ; then
F_printfp "########## TEST message ##########"
else
F_printfp "********** NOTICE **********"
fi
F_printfp "ASUS router has rebooted"
F_email_seperator # -----
F_printfpre "Model : ${fw_device_model}"
F_printfpre "Host/Domain : ${fw_pulled_device_name}.${fw_pulled_lan_name}"
F_printfpre "LAN IP : ${fw_lan_addr}"
F_email_seperator # -----
F_printfpre "Current router uptime : ${uptime_pretty}"
F_printfpre "Downtime after shutdown : $(printf '%3dd %2dh %2dm %2dsec\n' $((router_reboot_downtime/86400)) $((router_reboot_downtime%86400/3600)) $((router_reboot_downtime%3600/60)) $((router_reboot_downtime%60))) *"
F_printfpre "Uptime saved prior to reboot : $(printf '%3dd %2dh %2dm %2dsec\n' $((router_reboot_uptime/86400)) $((router_reboot_uptime%86400/3600)) $((router_reboot_uptime%3600/60)) $((router_reboot_uptime%60))) *"
F_printfpre "* approx"
[ -n "$user_custom_text_r" ] && F_email_seperator && F_printfpre "${user_custom_text_r_decoded}"
F_email_seperator # -----
F_printfp "Message sent: $(F_date f)"
F_printfp "Script ran with option : ${run_option}"
F_printfp "A message from wicens script v${script_version}"
# html footer
F_printfstr ''
F_printfstr ''
} > "$reboot_email"
[ "$sample_email" = 1 ] && return 0
###########################################################################
if [ -f "$wicens_reboot_retry" ] ; then
F_printfstr "Attempting to send reboot notification $(F_date r)" >> "$wicens_reboot_retry"
elif [ "$test_mode" = 0 ] ; then
{
F_printfstr "#!/bin/sh"
F_printfstr "wicens_reboot_retry_time=${run_epoch}"
F_printfstr "# Attempting to send reboot Email notification $(F_date r)"
} > "$wicens_reboot_retry"
F_chmod "$wicens_reboot_retry"
fi
F_internet_check reboot
if ! F_send_email; then
F_log_terminal_fail "Error - failed to send router reboot Email notification"
user_pswd=''
rm -f "$reboot_email"
cat "$mail_log" >> "$script_log_loc"
return 1
fi
user_pswd=''
rm -f "$reboot_email"
rm -f "$wicens_reboot_retry" 2> /dev/null
rm -f '/tmp/wicens_reboot_uptime.tmp' 2> /dev/null
rm -f '/tmp/wicens_reboot_downtime.tmp' 2> /dev/null
F_log_terminal_ok "Success sending router reboot Email notification"
F_replace_var reboot_notify_state 0 "$update_src"
return 0
} # reboot_email_msg
F_wanip_email_msg() {
[ "$sample_email" = 0 ] && F_log_terminal_ok "Attempting to send WAN IP change Email notification to $user_send_to_addr"
[ -f "$wanip_email" ] && rm -f "$wanip_email"
mail_file="$wanip_email"
F_uptime
if [ -n "$user_custom_subject_decoded" ] ; then
formatted_custom_subject="$(F_printfstr "$user_custom_subject_decoded" | \
/bin/sed "s~\$fw_device_model~$fw_device_model~g" | \
/bin/sed "s~\$current_wan_ip~$current_wan_ip~g" | \
/bin/sed "s~\$saved_wan_ip~$saved_wan_ip~g" | \
/bin/sed "s~\$fw_pulled_lan_name~$fw_pulled_lan_name~g" | \
/bin/sed "s~\$fw_pulled_device_name~$fw_pulled_device_name~g" | \
/bin/sed "s~\$fw_lan_addr~$fw_lan_addr~g")"
wan_subject="$formatted_custom_subject"
fi
{
# header
F_printfstr "From: \"${user_email_from}\" <${user_from_addr}>"
F_printfstr "To: \"${user_msg_to}\" <${user_send_to_addr}>"
[ -n "$user_send_to_cc" ] && F_printfstr "Cc: ${user_send_to_cc}"
F_printfstr "Subject: ${wan_subject}"
F_printfstr "Date: $(F_date r)"
# mime html
if [ "$sample_email" = 0 ] ; then
F_printfstr 'MIME-Version: 1.0'
F_printfstr 'Content-Type: text/html; charset="UTF-8"'
F_printfstr ''
F_printfstr ''
F_printfstr ''
F_printfstr ''
else
F_terminal_padding
fi
# body
if [ "$test_mode" = 1 ] && [ "$sample_email" = 0 ] ; then
F_printfp "########## TEST MESSAGE ##########"
else
F_printfp "********** NOTICE **********"
fi
F_printfp "WAN IP address has changed"
F_email_seperator # -----
F_printfpre "Model : ${fw_device_model}"
F_printfp "Host/Domain : ${fw_pulled_device_name}.${fw_pulled_lan_name}"
F_printfpre "LAN IP : ${fw_lan_addr}"
F_email_seperator # -----
if F_printfstr "$current_wan_ip" | F_cgnat_ip ; then
F_printfp "Warning - the new WAN IP is a CGNAT address"
F_printfp "You may not be able to access your router from anywhere outside your local network"
F_email_seperator # -----
fi
F_printfpre "New WAN IP : ${current_wan_ip}"
F_printfpre "Old WAN IP : ${saved_wan_ip}"
F_printfpre "Old WAN IP recorded in script : ${saved_wan_date}"
F_printfpre "Old WAN IP lease time observed : $(F_calc_lease)"
F_printfpre "Router uptime : ${uptime_pretty}"
[ -n "$user_custom_text" ] && F_email_seperator && F_printfpre "$(F_printf "${user_custom_text_decoded}")" # preserve custom text new lines
if [ -f "$history_src" ] ; then
F_email_seperator # -----
if [ "$(wc -l < "$history_src")" -ge 5 ]
then F_printfpre " WAN IP history (last ${wan_history_count}) most recent first"
else F_printfpre " WAN IP history most recent first"
fi
F_printfpre " Time Found IP Leased time"
F_email_seperator # -----
tail -n "$wan_history_count" < "$history_src" | /bin/sed 'x;1!H;$!d;x' | /bin/sed 's/.*/&<\/pre>/' # invert list
elif [ "$sample_email" = 1 ] || [ "$test_mode" = 1 ] ; then
F_email_seperator # -----
F_printfpre " WAN IP history most recent first"
F_printfpre " Time Found IP Leased Time"
F_email_seperator # -----
F_printfpre "Jan 01 2025 00:12:34 123.145.167.189 11d 12h 13m 14sec"
fi
F_email_seperator # -----
F_printfp "Message sent : $(F_date f)"
F_printfp "Script ran with option : ${run_option}"
F_printfp "A message from wicens v${script_version}"
# html footer
F_printfstr ''
F_printfstr ''
} > "$wanip_email"
###########################################################################
[ "$sample_email" = 1 ] && return 0
if [ -f "$wicens_wanip_retry" ] ; then
F_printfstr "# Attempting to send wan ip change notification $(F_date r)" >> "$wicens_wanip_retry"
elif [ "$test_mode" = 0 ] ; then
{
F_printfstr "#!/bin/sh"
F_printfstr "wicens_wanip_retry_time=${run_epoch}"
F_printfstr "# Attempting to send wan ip change notification $(F_date r)"
} > "$wicens_wanip_retry"
F_chmod "$wicens_wanip_retry"
fi
F_internet_check wanip
if ! F_send_email; then
# wanip email failed
user_pswd=''
rm -f "$wanip_email"
F_log_terminal_fail "Error, script failed to send Email notification"
F_log_show "Are your Email settings in this script correct? and password?"
F_log_show "Or maybe your Email host server was temporarily down?"
F_log_show "Main Menu - option L||l to view errors - P||p to re-enter password"
[ "$test_mode" = 0 ] && F_log_show "Resetting WAN IP to old WAN IP to attempt again in ${cron_check_freq} minutes"
cat "$mail_log" >> "$script_log_loc"
F_replace_var saved_wan_date "$original_wan_date" "$config_src"
F_replace_var saved_wan_epoch "$original_wan_epoch" "$config_src"
F_replace_var saved_wan_ip "$original_wan_ip" "$config_src"
case "$from_menu" in
1) F_menu_exit ;;
0) F_clean_exit ;;
esac
fi
# success cleanup
user_pswd=''
rm -f "$wanip_email"
rm -f "$wicens_wanip_retry" 2> /dev/null
case "$test_mode" in
0)
F_log_terminal_ok "Success sending Email notification, update devices to $current_wan_ip"
F_script_wan_update
;;
1) F_log_terminal_ok "Success sending test Email notification" ;;
esac
case "$from_menu" in
1)
case "$building_settings" in
0) F_menu_exit ;;
1) F_terminal_check_ok "This script is now configured" ; F_menu_exit ;;
esac
;;
esac
} # wanip_email_message
# EMAIL CONTROL #######################################################################################################
#######################################################################################################################
F_send_email() {
[ -f "$mail_log" ] && rm -f "$mail_log"
F_printfstr "Created by PID $$ on $(F_date r), ran by $run_option" > "$mail_log"
case "$amtm_import" in
1) user_pswd="$(eval "$(F_printfstr "$amtm_d" | openssl base64 -d)" < "$amtm_cred_loc")" ;;
0) [ "$user_message_type" != 'smtp_isp_nopswd' ] && user_pswd="$(eval "$(F_printfstr "$user_d" | openssl base64 -d)" < "$cred_loc")" ;;
esac
case "$user_message_type" in
'smtp_isp_nopswd') F_send_format_isp && return 0 ;;
'smtp_plain_auth') F_send_format_plain_auth && return 0 ;;
'smtp_start_tls') F_send_format_start_tls && return 0 ;;
'smtp_start_tls_v1') F_send_format_tls_v1 && return 0 ;;
'smtp_ssl') F_send_format_ssl && return 0 ;;
esac
return 1
} # send_email
F_send_format_isp() {
/usr/sbin/sendmail > "$mail_log" 2>&1 < "$mail_file" \
-S "$user_smtp_server" -f "$user_login_addr" -t "$user_send_to_addr" -v
} # send_format_isp
F_send_format_start_tls() {
/usr/sbin/sendmail >> "$mail_log" 2>&1 < "$mail_file" \
-H "exec /usr/sbin/openssl s_client -quiet \
-starttls smtp \
-connect $user_smtp_server \
-no_ssl3 -no_tls1" \
-t \
-f "$user_from_addr" -au"$user_login_addr" -ap"$user_pswd" "$user_send_to_addr" -v
} # send_format_tls
F_send_format_tls_v1() {
/usr/sbin/sendmail >> "$mail_log" 2>&1 < "$mail_file" \
-H "exec /usr/sbin/openssl s_client -quiet \
-tls1 -starttls smtp \
-connect $user_smtp_server" \
-t \
-f "$user_from_addr" -au"$user_login_addr" -ap"$user_pswd" "$user_send_to_addr" -v
} # send_format_tls1
F_send_format_plain_auth() {
/usr/sbin/sendmail >> "$mail_log" 2>&1 < "$mail_file" \
-t -S "$user_smtp_server" -f "$user_from_addr" "$user_send_to_addr" -au"$user_login_addr" -ap"$user_pswd" -v
} # send_format_plain_auth
F_send_format_ssl() {
ehlo_ip="\[$(F_nvram wan0_realip_ip)\]"
if [ -z "$user_send_to_cc" ] ; then
curl >> "$mail_log" 2>&1 \
-v \
--url "$protocol"://"$user_smtp_server"/"$ehlo_ip" \
--mail-from "$user_from_addr" --mail-rcpt "$user_send_to_addr" \
--upload-file "$mail_file" \
--ssl-reqd \
--crlf \
--user "$user_login_addr:$user_pswd" $ssl_flag
else
curl >> "$mail_log" 2>&1 \
-v \
--url "$protocol"://"$user_smtp_server"/"$ehlo_ip" \
--mail-from "$user_from_addr" --mail-rcpt "$user_send_to_addr" \
--mail-rcpt "$user_send_to_cc" \
--upload-file "$mail_file" \
--ssl-reqd \
--crlf \
--user "$user_login_addr:$user_pswd" $ssl_flag
fi
} # send_format_ssl
# SCRIPT UPDATES ######################################################################################################
#######################################################################################################################
F_web_update_check() {
if [ "$1" = 'force' ] ; then
F_terminal_header
F_terminal_show "${tYEL}===== Script Update Check =====${tCLR}"
else # update found running install, check again
[ "$update_avail" != 'none' ] && F_terminal_show "Confirming update ${tGRN}${update_avail}${tCLR} is most current "
orig_update="$update_avail" # keep note of original found update
fi
F_log_show "Checking for script update"
F_internet_check
# download wait timer for terminal git timeout 15secs
update_time=15
F_time() {
while [ "$update_time" != 0 ] ; do
F_term_waitdel "Checking for update ${tGRN}${update_time}${tCLR} secs"
update_time=$((update_time - 1))
sleep 1
printf '\r%b' "$tERASE"
done
}
# start terminal timer wait for var to set and kill timer
F_time & child_pid="${child_pid} $!"
git_version="$(F_git_get file | grep -Fm1 'script_version=' | cut -d'=' -f2 | sed "s/'//g")"
server_md5="$(F_git_get file | md5sum | awk '{print $1}')"
local_md5="$(md5sum "$script_name_full" | awk '{print $1}')"
sleep 2 # pretty terminal wait
if [ -z "$git_version" ] || [ -z "$server_md5" ] ; then
kill "$child_pid" > /dev/null 2>&1
printf '%b' "$tERASE$tBACK$tERASE"
F_log_terminal_fail "Failed, could not read server script version or calc md5, aborting update check"
F_wait 10
return 1 # skip everything below
fi
kill "$child_pid" > /dev/null 2>&1
F_replace_var update_cron_epoch "$(F_date s)" "$update_src"
if [ "$script_version" = "$git_version" ] ; then
if [ "$local_md5" != "$server_md5" ] ; then
F_replace_var update_avail "hotfix" "$update_src"
F_log "Success checking for update... hotfix available"
F_terminal_check_ok "${tGRN}Success${tCLR} checking for update... ${tRED}hotfix${tCLR} available"
F_terminal_padding
F_terminal_show "Change log:"
F_git_get hotfix
else
F_terminal_check_ok "${tGRN}Success${tCLR} checking for update... none available"
# cleanup, if no update found, make sure update file is correct
[ "$update_avail" != 'none' ] && F_replace_var update_avail 'none' "$update_src"
[ "$update_notify_state" = 1 ] && F_replace_var update_notify_state 0 "$update_src"
fi
else
F_replace_var update_avail "$git_version" "$update_src"
F_log "Success checking for update... v${git_version} available"
if [ "$1" = 'force' ] ; then # manual update check
F_terminal_check_ok "${tGRN}Success${tCLR} checking for update... Ver: ${tGRN}${git_version}${tCLR} available"
F_terminal_padding
F_terminal_show "Change log:"
F_git_get update
elif [ "$run_option" != 'cron' ] ; then # run by update installer verify newest or cron
F_terminal_check_ok "${tGRN}Success${tCLR} checking for update..."
if [ "$git_version" != "$orig_update" ] ; then
F_git_get update
F_log_terminal_ok "Will download newer version v${git_version} vs originally found update v${orig_update}"
else
F_terminal_check_ok "v${git_version} is the most current available update"
fi
F_terminal_check "Any key to continue..."
read -rsn1
fi
fi
source "$update_src" # resource config to update vars in current session
[ "$1" = 'force' ] && F_menu_exit
return 0
} # web_update_check
F_local_script_update() {
F_terminal_header
if [ "$update_avail" != 'none' ] && [ "$update_avail" != 'hotfix' ] ; then
F_terminal_show "Update available - version $update_avail"
elif [ "$update_avail" != 'none' ] && [ "$update_avail" = 'hotfix' ] ; then
F_terminal_show "Hotfix update available!"
fi
if ! F_confirm "Proceed with installing script update?" ; then
F_clean_exit reload
fi
if [ "$status_email_cfg" = 1 ] && [ ! -f "$script_backup_file" ] ; then
F_terminal_padding ; F_terminal_erase
F_terminal_warning
F_terminal_check_fail "No backup file exists for your config." ; F_terminal_padding
F_terminal_show "Continue upgrade without a backup?" ; F_terminal_padding
F_terminal_check "C||c to continue upgrade w/o backup - Any key to return to Main Menu"
read -rsn1 updatebackupwait
case "$updatebackupwait" in
C|c) clear ;;
*) F_clean_exit reload ;;
esac
fi
F_terminal_header
F_terminal_check_ok "Installing..."
F_terminal_check_ok "Starting script update to ver: $update_avail"
# time between update found and current re-check give 60secs for menu update vs mail notification
if [ "$(($(F_date s) - update_cron_epoch))" -gt 60 ] ; then
F_web_update_check # confirm saved update avail is current, notify if not
F_terminal_header
fi
F_terminal_check "Downloading...."
sleep 2
if F_git_get download ; then
F_terminal_check_ok "Success, script version $update_avail installed"
# reset email notification for script update
[ "$update_notify_state" = 1 ] && F_replace_var update_notify_state 0 "$update_src"
else
F_terminal_check_fail "Error, failed downloading/saving new script version"
F_menu_exit
fi
F_terminal_padding
git_version="$(grep -Fm1 'script_version=' "$script_name_full" | cut -d'=' -f2 | sed "s/'//g")" # cut script version number from downloaded file
F_terminal_show "Change log:"
case "$update_avail" in
'hotfix') F_git_get hotfix ;;
*) F_git_get update ;;
esac
F_replace_var update_avail "none" "$update_src"
F_replace_var update_date "$(F_date f)" "$config_src"
F_terminal_padding
F_log_terminal_ok "This install has been upgraded to version $git_version"
F_terminal_check "Any key to continue..."
read -rsn1
F_clean_exit reset
} # local_script_update
F_integrity_check() {
if [ "$update_settings_version" != "$current_core_config" ] ; then # if new updated core config differs from saved, update
old_version="$update_settings_version"
F_terminal_header
F_log_terminal_fail "Current script core config v${update_settings_version} is not current, starting update"
config_updated=1 # prevents install message
# current file is already sourced, remove file and change new file with loaded vars
rm -f "$update_src"
F_default_update_create
source "$update_src" # reset loaded for F_firmware_check
F_log_terminal_ok "core config v${current_core_config} created, updating with current settings"
[ "$(F_printf "$update_settings_version" | cut -d'.' -f1)" -le 3 ] && max_fw_nvram_check=0 # v3->v4 new config not yet sourced
# if cron(cru) services-start wan-event enabled remove and reload
if F_cru check ; then
F_cru remove
F_cru create
F_log_terminal_ok "Updated cron(cru) entry"
fi
if F_serv_start check ; then
F_serv_start remove
F_serv_start create
F_log_terminal_ok "Updated services-start entry"
fi
if F_wan_event check ; then
F_wan_event remove
F_wan_event create
F_log_terminal_ok "Updated wan-event entry"
fi
F_printfstr "# Updated : v${old_version} to v${current_core_config} $(F_date r)" >> "$update_src"
F_log_terminal_ok "Done, updated core config file from v${old_version} to v${current_core_config}"
source "$update_src"
fi
if [ "$build_settings_version" != "$current_user_config" ] ; then # if new updated user config differs from saved, update
[ "$config_updated" != 1 ] && F_terminal_header # only if we didnt update core config
[ -n "$restore" ] && F_log_terminal_fail "Loaded backup config is outdated"
F_log_terminal_fail "Current script user config v${build_settings_version} is not current, starting update"
# current file is already sourced, remove file and change new file with loaded vars
rm -f "$config_src"
F_default_user_create
F_log_terminal_ok "user config v${current_user_config} created, updating with current user settings"
# v3->v4 adjustments ################### set new vars/format v3 vars/set new v4 vars w/loaded v3 config
if [ "$(F_printfstr "$build_settings_version" | cut -d'.' -f1)" -le 3 ] ; then
# added vars
user_wanip_notification=1 # we assume if v3, wanip was enabled
user_reboot_notification=0
user_email_from='wicens script'
# states are inverted
if [ "$amtm_import" = 0 ] ; then amtm_import=1 ; else amtm_import=0 ; fi
if [ "$user_update_notification" = 0 ] ; then user_update_notification=1 ; else user_update_notification=0 ; fi
if [ "$user_fw_update_notification" = 0 ] ; then user_fw_update_notification=1 ; else user_fw_update_notification=0 ; fi
if [ "$log_cron_msg" = 0 ] ; then log_cron_msg=1 ; else log_cron_msg=0 ; fi
# var names were changed
user_login_addr="$user_from_addr"
user_from_addr="$user_from_name"
# set to never if empty
[ -z "$last_cron_run" ] && last_cron_run='never'
[ -z "$last_wancall_run" ] && last_wancall_run='never'
[ -z "$last_ip_change" ] && last_ip_change='never'
[ -z "$update_date" ] && update_date='never'
# change to new date format
for var_update in last_cron_run last_wancall_run last_ip_change install_date update_date saved_wan_date created_date
do
new_value="$(eval "F_printfstr \"\${$var_update}\"" )"
if [ -n "$new_value" ] && [ "$new_value" != 'never' ] ; then
new_value="$(F_printfstr "$new_value" | sed 's/^... //;s/@ //g')"
eval "$var_update=\"\$new_value\""
else
F_replace_var "$var_update" 'never' "$config_src" # if blank in v3 force to never
fi
done
if [ -f "$history_src" ] ; then
sed -i 's/^... //;s/@ //g' "$history_src"
fi
# new color set vars
case "$opt_color" in
'yes') opt_color=1 ;;
'no') opt_color=0 ;;
esac
[ -f '/tmp/wicens.lock' ] && rm -f /tmp/wicens.lock # remove old v3 lock
fi
# end of v3->v4
# v4.0->v4.1 wanip_monitor/user_msg_to
[ -z "$user_msg_to" ] && user_msg_to='wicens user'
if [ -z "$user_wanip_monitor" ] ; then
case "$user_wanip_notification" in
1) user_wanip_monitor=1
F_replace_var user_wanip_monitor '1' "$config_src"
;;
0) user_wanip_monitor=0
F_replace_var user_wanip_monitor '0' "$config_src"
;;
esac
fi
# update values in new default config with currently loaded config
# build list of vars to update from old config, read them from old and set them
sed '/#/d' "$config_src" | cut -d'=' -f1 | sed '/build_settings_version/d' | cut -d'=' -f1 > /tmp/wicens_config_copy.tmp
while IFS= read -r config_line
do
value=$(eval F_printfstr "\"\$$config_line\"")
F_replace_var "$config_line" "$value" "$config_src"
done < '/tmp/wicens_config_copy.tmp'
rm -f /tmp/wicens_config_copy.tmp
F_printfstr "# Updated : v${build_settings_version} to v${current_user_config} $(F_date r)" >> "$config_src"
F_log_terminal_ok "Done, updated user config file from v${build_settings_version} to v${current_user_config}"
config_updated=1 # prevents install message
source "$config_src"
fi
if [ "$config_updated" = 1 ] ; then
fw_nvram_check_diff=$((max_fw_nvram_check + 1)) # if updated config force firmware check update
F_firmware_check
F_wait 60
F_clean_exit reset
fi
return 0
} # integrity_check
# INTERNET ############################################################################################################
#######################################################################################################################
F_internet_ping() {
# we ping websites to confirm DNS works for mail server lookup
cycle_ping_count=1 # cycle through 15 good/bad pings if necessary till 6 good
good_ping=0
last_random= # last random site chosen array
while [ "$cycle_ping_count" -le 5 ] ; do # 5 cycles x 3ping/cycle = 15 total failed / pass with 6 successful attempts
random_site="$(F_random_num $(F_test_sites | wc -l))" # pick random line #
[ "${#last_random}" -ge 4 ] && last_random= # refresh random array after 4 unique tests
# if random picks one of last 3 recently tested sites try again
if ! F_printfstr "$last_random" | grep -Fq "$random_site" ; then
last_random="${last_random}$random_site" # create array of tested sites from random_site
tested_site="$(F_test_sites | sed -n "${random_site}p")" # read line from list
ping_try_count=0
site_ping=0
while [ "$ping_try_count" -ne 3 ] ; do # ping site 3 times if fail then move on/otherwise 2 good move on
if ping -q -w1 -c1 "$tested_site" > /dev/null 2>&1 ; then
good_ping=$((good_ping + 1))
site_ping=$((site_ping + 1))
[ "$good_ping" -ge 6 ] && return 0
[ "$site_ping" -ge 2 ] && break
fi
ping_try_count=$((ping_try_count + 1))
done
cycle_ping_count=$((cycle_ping_count + 1))
fi
done
return 1
} # internet_ping cycle through 2good/3bad pings to each random site till 6 good or 15 cycle attempts
F_internet_check() {
internet_check_count=0
F_printfstr "$(F_date s)" > "$internet_lock"
# 10 attempts
while [ "$internet_check_count" -le 11 ] ; do
internet_check_count=$((internet_check_count + 1))
# failed cleanup exit
if [ "$internet_check_count" -eq 11 ] ; then
F_log_terminal_fail "Could not ping $(F_test_sites | wc -l) test sites for the last 5 mins, exiting. Run again with next cron"
# remove entry from wanip,send,update,fwupdate to retry again after internet up
if [ -n "$1" ] ; then
case "$1" in
'wanip') file_line_remove="$wicens_wanip_retry" ;;
'send') file_line_remove="$wicens_send_retry" ;;
'update') file_line_remove="$wicens_update_retry" ;;
'fwupdate') file_line_remove="$wicens_fw_retry" ;;
'reboot') file_line_remove="$wicens_reboot_retry" ;;
esac
sed '$d' "$file_line_remove"
F_log "Removed retry line from $file_line_remove"
fi
rm -f "$internet_lock"
F_clean_exit
fi
# ping test
F_terminal_check "Checking Internet status..."
if F_internet_ping ; then
[ "$1" != 'mini' ] && F_log_terminal_ok "Internet check 6 successful pings, appears up"
break
else
F_log_terminal_fail "Failed pings to 3-5 sites, Internet down?"
wait_secs=30
while [ "$wait_secs" -ne 0 ] ; do
F_term_waitdel "$wait_secs before next attempt"
sleep 1
wait_secs=$((wait_secs - 1))
done
fi
done
rm -f "$internet_lock"
return 0
} # internet_check
# WAN IP ##############################################################################################################
#######################################################################################################################
F_compare() {
[ "$fw_sw_mode" = 1 ] && F_terminal_check_ok "Getting current WAN IP from nvram"
current_wan_ip="$(F_nvram wan0_ipaddr)"
if [ -z "$current_wan_ip" ] || [ "$current_wan_ip" = '0.0.0.0' ] ; then
if [ "$fw_sw_mode" = 1 ] ; then
F_log_terminal_fail "No valid IP found in NVRAM, checking with getrealip.sh" # log nothing in nvram
F_getrealip
else
F_ministun
fi
elif F_printfstr "$current_wan_ip" | F_private_ip ; then
F_terminal_check_fail "nvram WAN IP ${current_wan_ip} is a private IP, using wan0_realip_ip" # don't log if WAN IP is private (double nat)
current_wan_ip="$(F_nvram wan0_realip_ip)"
if [ -z "$current_wan_ip" ] || [ "$current_wan_ip" = '0.0.0.0' ] ; then
if [ "$fw_sw_mode" = 1 ] ; then
F_terminal_check_fail "nvram wan0_realip_ip is empty forcing update with getrealip.sh"
F_getrealip
else
F_ministun
fi
fi
fi
# is WAN IP valid
if F_printfstr "$current_wan_ip" | F_private_ip ; then
F_log_terminal_fail "WAN IP ${current_wan_ip} is a private IP, something is wrong"
[ "$run_option" = 'tty' ] && F_menu_exit
F_clean_exit error
fi
if [ "$current_wan_ip" = "$saved_wan_ip" ] ; then
F_terminal_check_ok "WAN IP lookup - Current WAN IP : ${tGRN}${current_wan_ip}${tCLR}"
F_terminal_check_ok "WAN IP compare - Saved WAN IP : ${tGRN}${saved_wan_ip}${tCLR}"
[ "$run_option" = 'wancall' ] && F_log "Saved WAN IP matches current IP" # verify wan-event checks
if F_printfstr "$current_wan_ip" | F_cgnat_ip ; then
F_terminal_fail "Notice - Your WAN IP ${current_wan_ip} appears to be a CGNAT address"
fi
return 0
else
F_terminal_check_ok "WAN IP lookup - Current WAN IP : ${tGRN}$current_wan_ip${tCLR}"
F_terminal_check_fail "WAN IP compare - Saved WAN IP : ${tRED}$saved_wan_ip${tCLR}"
[ -n "$saved_wan_ip" ] && [ "$building_settings" = 0 ] && F_log_terminal_fail "WAN IP has changed to ${current_wan_ip} "
if F_printfstr "$current_wan_ip" | F_cgnat_ip ; then
F_log_terminal_fail "Notice - New WAN IP ${current_wan_ip} appears to be a CGNAT address"
fi
# user_custom_script 'immediate' call
[ "$run_option" = 'tty' ] && [ -n "$user_custom_script" ] && F_terminal_show "Notice - custom script is set to execute but will not run in terminal IP compare"
if [ -n "$user_custom_script" ] && [ "$building_settings" = 0 ] && [ "$test_mode" = 0 ] && [ ! -f '/tmp/wicens_user_script_i.tmp' ] && [ "$run_option" != 'tty' ] ; then
if [ "$user_custom_script_time" = 'i' ] ; then
nohup /bin/sh "$user_custom_script_decoded" "$current_wan_ip" > "$user_script_log" 2>&1 & custom_script_pid=$!
F_log_terminal_ok "Executed custom script ${user_custom_script_decoded} and put in background with PID ${custom_script_pid}"
touch /tmp/wicens_user_script_i.tmp # prevent duplicate runs if email fails on first detection as this will run
fi
fi
return 1
fi
} # compare
F_getrealip() {
F_internet_check
getrealip_cnt="$getrealip_max" # max tries to get WAN IP
F_doiplook() { # watcher for getrealip.sh so if it hangs it doesnt sit around forever
(sh /usr/sbin/getrealip.sh | grep -Eo "$ip_regex" ) & command_pid=$!
(sleep 5 && /bin/kill -HUP "$command_pid" 2> /dev/null && rm -f /tmp/wicenswanipget.tmp && F_log_terminal_fail 'Notice - Killed hung getrealip.sh process after 5 secs' ) & watcher_pid=$!
wait "$command_pid" && /bin/kill -HUP "$watcher_pid" 2> /dev/null
getrealip_cnt=$((getrealip_cnt - 1))
} # getrealip
while [ "$getrealip_cnt" -ne 0 ] ; do
F_terminal_check_ok "Retrieving WAN IP using /usr/sbin/getrealip.sh (STUN lookup)"
F_doiplook > /tmp/wicenswanipget.tmp # output to file or watcher doesnt function properly when var=
current_wan_ip="$(grep -Eo "$ip_regex" /tmp/wicenswanipget.tmp 2> /dev/null)"
[ -f /tmp/wicenswanipget.tmp ] && rm -f /tmp/wicenswanipget.tmp
if [ "$current_wan_ip" = '0.0.0.0' ] || [ -z "$current_wan_ip" ] ; then
if [ "$getrealip_cnt" -eq 0 ] ; then
F_log_terminal_fail "Error retrieving WAN IP ${getrealip_max} times, aborting"
F_clean_exit error
else
reattempt="$(F_random_num 15)"
F_terminal_check_fail "Error retrieving WAN IP with getrealip.sh, attempt again in ${reattempt} secs"
sleep "$reattempt"
F_terminal_erase
fi
else
break
fi
done
return 0
} # getrealip
F_ministun() {
last_random_mini=
F_internet_check mini
stun_list="$(F_stun_servers | wc -l)"
stun_count="$stun_max" # copy stun_max from config for writeable var
while [ "$stun_count" -gt 0 ] ; do
server_attempt=0
while [ "${#server_attempt}" -lt "$stun_list" ] ; do
server_random="$(F_random_num $stun_list)"
if ! F_printfstr "$last_random_mini" | grep -Fq "$server_random" ; then
last_random_mini="${last_random_mini}$server_random"
server_attempt=$((server_attempt + 1))
stun_server="$(F_stun_servers | sed -n "${server_random}p")"
F_terminal_check_ok "Retrieving WAN IP w/ STUN server: ${tGRN}${stun_server}${tCLR}"
current_wan_ip="$(ministun -t 1000 -c 1 "$stun_server" 2>/dev/null)"
[ $? = 0 ] && break
F_terminal_check_fail "Failed lookup at STUN server: ${stun_server}"
current_wan_ip=
fi
done
if [ "$current_wan_ip" = '0.0.0.0' ] || [ -z "$current_wan_ip" ] ; then
if [ "$stun_count" -eq 1 ] ; then
F_log_terminal_fail "Error retrieving WAN IP with ministun ${stun_max} times at ${stun_list} servers... aborting"
case "$run_option" in
'tty') F_menu_exit ;;
esac
F_clean_exit error
else
reattempt="$(F_random_num 15)"
F_terminal_check_fail "Error retrieving WAN IP with ministun, attempt again in ${reattempt} secs"
sleep "$reattempt"
F_terminal_erase
stun_count=$((stun_count - 1))
fi
else
break
fi
done
return 0
} # ministun
F_calc_lease() {
current_epoch="$(F_date s)"
[ -n "$saved_wan_epoch" ] && epoch_diff=$((current_epoch - saved_wan_epoch))
if [ -z "$saved_wan_epoch" ] ; then
F_printfstr ' 0d 0h 0m 0sec'
else
F_printfstr "$(printf '%3dd %2dh %2dm %2dsec\n' $((epoch_diff/86400)) $((epoch_diff%86400/3600)) $((epoch_diff%3600/60)) $((epoch_diff%60)))"
fi
} # calc_lease
F_script_wan_update() {
[ -z "$saved_wan_ip" ] && building_settings=1
if [ "$building_settings" = 1 ] ; then # first run
F_terminal_check_ok "Current WAN IP ${current_wan_ip} successfully retrieved"
else
# write IP history records before updating
F_replace_var last_ip_change "$(F_date f)" "$config_src"
printf '%-20s %-15s %s\n' "$saved_wan_date" "$saved_wan_ip" "$(F_calc_lease)" >> "$history_src"
ip_change_count=$((ip_change_count + 1)) # update script IP changes after success
F_replace_var ip_change_count "$ip_change_count" "$config_src"
# user_custom_script 'wait' call
[ "$run_option" = 'tty' ] && [ -n "$user_custom_script" ] && [ "$user_custom_script_time" = 'w' ] && F_terminal_show "Notice - custom script is set to execute but will not run in terminal IP compare"
if [ -n "$user_custom_script" ] && [ "$user_custom_script_time" = 'w' ] && [ "$run_option" != 'test' ] && [ "$run_option" != 'tty' ] ; then
nohup /bin/sh "$user_custom_script_decoded" "$current_wan_ip" > "$user_script_log" & custom_script_pid=$!
F_log_terminal_ok "Executed custom script ${user_custom_script_decoded} and put in background with PID ${custom_script_pid}"
fi
# clean up custom script 'immediate' call lock
if [ -f /tmp/wicens_user_script_i.tmp ] && [ "$test_mode" = 0 ] ; then
rm -f /tmp/wicens_user_script_i.tmp # immediate call lock file remove after success
fi
fi
F_replace_var saved_wan_ip "$current_wan_ip" "$config_src"
F_replace_var saved_wan_date "$(F_date f)" "$config_src"
F_replace_var saved_wan_epoch "$(F_date s)" "$config_src"
F_log_terminal_ok "Updated script with WAN IP ${current_wan_ip}"
return 0
} # script_wan_update
# AUTO RUN ############################################################################################################
#######################################################################################################################
F_cru() {
case "$1" in
'check')
cru l | grep -Fq "$script_name_full" && status_cru=1 && return 0
status_cru=0 && return 1
;;
'create')
cru a wicens "${cron_string}"
F_log_terminal_ok "Added entry in cron(cru) with ${cron_check_freq}m interval"
F_cru check # update status_cru immediately
;;
'remove')
if F_cru check ; then
cru d wicens
F_log_terminal_ok "Removed entry in cron(cru)"
else
F_log_terminal_ok "No entry in cron(cru) to remove"
fi
F_cru check # update status_cru immediately
;;
esac
return 0
} # cru
F_serv_start() {
case "$1" in
'check')
grep -Fq "${script_name_full} cron" /jffs/scripts/services-start 2> /dev/null && status_srvstrt=1 && return 0
status_srvstrt=0 && return 1
;;
'create')
if [ -f /jffs/scripts/services-start ] ; then
F_crlf '/jffs/scripts/services-start'
F_chmod '/jffs/scripts/services-start'
if ! grep -Fq '#!/bin/sh' /jffs/scripts/services-start ; then
sed -i '1 i\#!/bin/sh' /jffs/scripts/services-start
F_log_terminal_fail "Your services-start does not contain a '#!/bin/sh'"
F_log_terminal_ok "Added #!/bin/sh to top of services-start file"
fi
{
F_printfstr "/usr/sbin/cru a wicens \"${cron_string}\" # added by wicens $(F_date r)"
F_printfstr "/usr/bin/logger -t \"services-start[\$\$]\" \"Added wicens entry to cron(cru)\" # added by wicens $(F_date r)"
} >> /jffs/scripts/services-start
F_log_terminal_ok "Added entry in /jffs/scripts/services-start for cron(cru)"
else
{
F_printfstr "#!/bin/sh"
F_printfstr "# Created by ${script_name_full} for WAN IP change notification $(F_date r)"
F_printfstr "/usr/sbin/cru a wicens \"${cron_string}\" # added by wicens $(F_date r)"
F_printfstr "/usr/bin/logger -t \"services-start[\$\$]\" \"Added wicens entry to cron(cru)\" # added by wicens $(F_date r)"
} > /jffs/scripts/services-start
F_chmod '/jffs/scripts/services-start'
F_log_terminal_ok "Created /jffs/scripts/services-start and added entry for cron(cru)"
fi
F_serv_start check
;;
'remove')
if [ -f /jffs/scripts/services-start ] ; then
if grep -Fq "${script_name_full} cron" /jffs/scripts/services-start ; then
sed -i '/added by wicens/d' /jffs/scripts/services-start
F_log_terminal_ok "Removed entry in /jffs/scripts/services-start for cron(cru)"
else
F_log_terminal_ok "No entry in /jffs/scripts/services-start for cron(cru) to remove"
fi
if [ "$(wc -l < /jffs/scripts/services-start )" -eq 1 ] ; then
if grep -Fq '#!/bin/sh' /jffs/scripts/services-start ; then
F_log_terminal_ok "/jffs/scripts/services-start appears empty, removing file"
rm -f /jffs/scripts/services-start
fi
fi
else
F_log_terminal_ok "No entry in /jffs/scripts/services-start for cron(cru), file doesn't exist"
fi
F_serv_start check
;;
esac
return 0
} # serv_start
F_wan_event() {
case "$1" in
'check')
grep -Fq "${script_name_full} wancall" /jffs/scripts/wan-event 2> /dev/null && status_wanevent=1 && return 0
status_wanevent=0 && return 1
;;
'create')
if [ -f /jffs/scripts/wan-event ] ; then
F_crlf '/jffs/scripts/wan-event'
F_chmod '/jffs/scripts/wan-event'
if ! grep -Fq '#!/bin/sh' /jffs/scripts/wan-event ; then
sed -i '1 i\#!/bin/sh' /jffs/scripts/wan-event
F_log_terminal_fail "Your wan-event does not contain a '#!/bin/sh'"
F_log_terminal_ok "Added #!/bin/sh to top of wan-event file"
fi
{
F_printfstr "[ \"\$2\" = \"connected\" ] && nohup sh ${script_name_full} wancall & wicenspid=\$! # added by wicens $(F_date r)"
F_printfstr "[ \"\$2\" = \"connected\" ] && /usr/bin/logger -t \"wan-event[\$\$]\" \"Started wicens with pid \${wicenspid}\" # added by wicens $(F_date r)"
} >> /jffs/scripts/wan-event
F_log_terminal_ok "Added entry in /jffs/scripts/wan-event with connected event trigger"
else
{
F_printfstr "#!/bin/sh"
F_printfstr "# Created by ${script_name_full} for WAN IP change notification # added by wicens $(F_date r)"
F_printfstr "[ \"\$2\" = \"connected\" ] && nohup sh ${script_name_full} wancall & wicenspid=\$! # added by wicens $(F_date r)"
F_printfstr "[ \"\$2\" = \"connected\" ] && /usr/bin/logger -t \"wan-event[\$\$]\" \"Started wicens with pid \${wicenspid}\" # added by wicens $(F_date r)"
} > /jffs/scripts/wan-event
F_chmod '/jffs/scripts/wan-event'
F_log_terminal_ok "Created /jffs/scripts/wan-event and added connected event trigger"
fi
F_wan_event check
;;
'remove')
if [ -f /jffs/scripts/wan-event ] ; then
if grep -Fq "${script_name_full} wancall" /jffs/scripts/wan-event ; then
sed -i '/added by wicens/d' /jffs/scripts/wan-event
F_log_terminal_ok "Removed entry in /jffs/scripts/wan-event"
else
F_log_terminal_ok "No entry in /jffs/scripts/wan-event to remove"
fi
if [ "$(wc -l < /jffs/scripts/wan-event)" -eq 1 ] ; then
if grep -Fq '#!/bin/sh' /jffs/scripts/wan-event ; then
F_log_terminal_ok "/jffs/scripts/wan-event appears empty, removing file"
rm -f /jffs/scripts/wan-event
fi
fi
else
F_log_terminal_ok "No entry in /jffs/scripts/wan-event - file doesn't exist"
fi
F_wan_event check
;;
esac
return 0
} # wan_event
F_auto_run() {
case "$1" in
'createall')
if [ "$status_cru" = 0 ] ; then F_cru create ; else F_terminal_check_ok "cron(cru) entry already enabled" ; fi
if [ "$status_srvstrt" = 0 ] ; then F_serv_start create ; else F_terminal_check_ok "services-start entry already enabled" ; fi
if [ "$status_wanevent" = 0 ] ; then
if [ "$fw_sw_mode" = 1 ]
then F_wan_event create # only enable wan-event if in router mode
else F_terminal_check_ok "Not in router mode, skipping wan-event"
fi
else
F_terminal_check_ok "wan-event entry already enabled"
fi
;;
'create2')
if [ "$status_cru" = 0 ] ; then F_cru create ; else F_terminal_check_ok "cron(cru) entry already enabled" ; fi
if [ "$status_srvstrt" = 0 ] ; then F_serv_start create ; else F_terminal_check_ok "services-start entry already enabled" ; fi
;;
'removeall')
F_cru remove
F_serv_start remove
F_wan_event remove
;;
'remove2')
F_cru remove
F_serv_start remove
;;
'testall')
F_cru check
F_serv_start check
F_wan_event check
;;
esac
return 0
} # auto_run
# SETTINGS TEST #######################################################################################################
#######################################################################################################################
F_settings_test() {
# amtm check valid/load ###################################################
status_amtm=0
if F_amtm check ; then
case "$amtm_import" in
1) F_amtm load ;;
esac
status_amtm=1
fi
case "$amtm_import" in
1)
case "$status_amtm" in
0)
F_terminal_header
F_log_terminal_fail "Error - script set to load amtm settings but amtm settings invalid"
F_log_terminal_fail "Notice - disabling amtm import, run script to re-enable"
F_replace_var amtm_import 0 "$config_src"
if [ "$run_option" != 'tty' ] ; then
F_log_show "If valid settings were created inside this script, will try with those settings"
else
F_wait 15
fi
;;
esac
;;
esac
# email settings valid ####################################################
status_email_cfg=1
[ -z "$user_login_addr" ] && [ -n "$user_from_addr" ] && user_login_addr="$user_from_addr" # v3-v4 opt_restore status page
if [ -z "$user_from_addr" ] || [ -z "$user_message_type" ] || [ -z "$user_send_to_addr" ] || [ -z "$user_smtp_server" ] || [ -z "$user_login_addr" ] ; then
status_email_cfg=0
[ "$run_option" != 'tty' ] && [ "$user_wanip_monitor" = 0 ] && F_log "Missing core settings"
fail_reason="$(printf "[%bFAIL%b] Missing core Email settings \n\n" "$tRED" "$tCLR")"
elif [ ! -f "$cred_loc" ] && [ "$user_message_type" != 'smtp_isp_nopswd' ] && [ "$status_email_cfg" = 1 ] && [ "$amtm_import" = 0 ] ; then
fail_reason="$(printf "[%bFAIL%b] Email send type set to %s but missing required password \n\n" "$tRED" "$tCLR" "$user_message_type")"
[ "$run_option" != 'tty' ] && [ "$user_wanip_monitor" = 0 ] && F_log "Email send type set to ${user_message_type} but missing required password"
status_email_cfg=0
fi
# auto-run services #######################################################
F_auto_run testall
# config file sanity checks ###############################################
# email settings dont exist disable all
case "$status_email_cfg" in
0)
[ "$user_wanip_notification" = 1 ] && F_notify_wanip remove nouser
[ "$user_update_notification" = 1 ] && F_notify_update remove
[ "$user_fw_update_notification" = 1 ] && F_notify_firmware remove
[ "$user_reboot_notification" = 1 ] && F_notify_reboot remove
;;
esac
# enabled option dependencies check #######################################
if [ -z "$restore" ] ; then # only if not run with backup restore
# check wan ip notification dependencies
[ "$user_wanip_notification" = 1 ] && [ "$user_wanip_monitor" = 0 ] && F_wanip_monitor create
# check monitor depenencies
if [ "$user_wanip_monitor" = 1 ] ; then
if [ "$fw_sw_mode" = 1 ] ; then
if [ "$status_cru" = 0 ] || [ "$status_srvstrt" = 0 ] || [ "$status_wanevent" = 0 ] ; then
F_auto_run createall
fi
else
if [ "$status_cru" = 0 ] || [ "$status_srvstrt" = 0 ] ; then
F_auto_run create2
fi
fi
else
[ "$status_wanevent" = 1 ] && F_wan_event remove
fi
# notifications disabled but auto runs exist - remove them ############
if [ "$status_cru" = 1 ] || [ "$status_srvstrt" = 1 ] ; then
if [ "$user_wanip_notification" = 0 ] && [ "$user_reboot_notification" = 0 ] && [ "$user_fw_update_notification" = 0 ] && [ "$user_update_notification" = 0 ] && [ "$user_wanip_monitor" = 0 ] ; then
F_auto_run removeall > /dev/null 2<&1
fi
fi
# notifications enabled but no auto run exists - create auto runs #####
if [ "$user_update_notification" = 1 ] || [ "$user_reboot_notification" = 1 ] || [ "$user_fw_update_notification" = 1 ] ; then
if [ "$status_cru" = 0 ] || [ "$status_srvstrt" = 0 ] ; then
F_auto_run create2
fi
fi
# firmware enabled but no entry in update-notification - add it #######
if [ "$user_fw_update_notification" = 1 ] ; then
! F_notify_firmware check status && F_notify_firmware create
fi
# reboot enabled but no entry in services-start - add it ##############
if [ "$user_reboot_notification" = 1 ] ; then
! F_notify_reboot check status && F_notify_reboot create
fi
# custom script file check (spam the log) - auto disable w/tty ########
if [ -n "$user_custom_script" ] ; then
if [ ! -f "$user_custom_script_decoded" ] ; then
F_log_terminal_fail "Error - custom script ${user_custom_script_decoded} is set to run but file is not there"
else
[ -z "$user_custom_script_time" ] && F_log_terminal_fail "Error - custom script is set to run but runtime is missing"
fi
F_wanip_monitor check # havent yet checked
F_notify_wanip check
if [ "$status_wanipmon" = 0 ] ; then
F_log_terminal_fail "Error - custom script ${user_custom_script_decoded} is set to run but WAN IP monitor is not enabled, removing"
F_opt_script remove
[ "$run_option" = 'tty' ] && F_wait 15
else
if [ "$status_wanip" = 0 ] && [ "$user_custom_script_time" = 'w' ] ; then
F_log_terminal_fail "Error - custom script time set to wait but WAN IP Email disabled"
F_replace_var user_custom_script_time 'i' "$config_src"
F_log_terminal_ok "Switched custom script time to immediate"
[ "$run_option" = 'tty' ] && F_wait 15 && F_clean_exit reload
fi
fi
fi
fi
# CHECK NOTIFY STATUS FOR MENU ############################################
F_notify_firmware check
F_notify_reboot check
F_notify_update check
F_notify_wanip check
F_wanip_monitor check
# CLEAN UP ################################################################
# only with tty
case "$run_option" in
'tty')
# clean old user_pswd if setup was edited/proper config doesnt exist
if [ "$status_email_cfg" = 0 ] || [ "$user_message_type" = 'smtp_isp_nopswd' ] ; then
if [ -f "$cred_loc" ] ; then
rm -f "$cred_loc"
F_terminal_header
F_log_show "Removed old saved password, invalid Email type or invalid Email settings"
[ "$run_option" = 'tty' ] && F_wait 10
fi
fi
# cleanup password backup if config backup doesnt exist ###########
[ -f "$cred_loc_bak" ] && [ ! -f "$script_backup_file" ] && rm -f "$cred_loc_bak"
# started custom script entry and wrote time but exited ###########
[ -n "$user_custom_script_time" ] && [ -z "$user_custom_script" ] && F_replace_var user_custom_script_time '' "$config_src"
# custom script loaded but can no longer find script ##############
if [ -n "$user_custom_script" ] && [ ! -f "$user_custom_script_decoded" ] ; then
F_terminal_header
F_terminal_warning
F_terminal_check_fail "Custom script set to $user_custom_script_decoded but can't find file"
F_terminal_padding
F_log_show "Disabling custom script on WAN IP change option"
F_terminal_padding
F_opt_script remove
F_wait 15
fi
;;
esac
return 0
} # settings_test
F_ready_check() {
[ "$status_wanipmon" = 1 ] && return 0 # if wanipmon enabled we dont care if email is configured for cron to run
case "$status_email_cfg" in
0)
if [ "$run_option" = 'tty' ] && [ "$from_menu" = 1 ] ; then
[ "$1" = 'pswdset' ] && return 0
[ "$1" != 'options' ] && F_terminal_header # not sent here from a menu option, displayed already
F_terminal_check_fail "Error - no Email settings have been setup"
F_terminal_padding
F_terminal_show "Use menu option 1 to add settings"
F_menu_exit
else
F_log "Error - no config or incomplete Email config found in this script"
F_log "Run $script_name_full to add a config to this script"
F_clean_exit error
fi
;;
1) # passes test but trying to establish pswd with isp_type or incomplete settings
case "$1" in
'pswdset')
if [ "$user_message_type" = 'smtp_isp_nopswd' ] ; then
F_terminal_padding
F_terminal_check_fail "Cannot add password, SMTP type is set to ISP type"
F_terminal_padding
F_menu_exit
fi
;;
esac
return 0
;;
esac
} # ready_check
# STATUS/TERMINAL #####################################################################################################
#######################################################################################################################
F_terminal_header() {
clear
case "$1" in
exit) sed -n '3,8p' "$script_name_full" | sed 's/#//g' | sed 's/^.\{14\}//' ; return 0 ;;
'') sed -n '2,11p' "$script_name_full" ; F_printf "${tBACK}${tBACK}# pid $$ v${script_version}\n" ;;
esac
case "$fw_build_no" in
'384'|'386'|'388') F_printf " ${tGRN}$(F_date r)${tCLR} Model: ${tGRN}${fw_device_model}${tCLR} FW: ${tGRN}${fw_build_full}${tCLR}" ;;
'374') F_printf " ${tGRN}$(F_date r)${tCLR} ${tGRN}${fw_device_model}${tCLR} FW ver: ${tGRN}${fw_build_no}.${fw_build_extend}${tCLR}" ;;
esac
F_terminal_separator
case "$building_settings" in
1)
F_terminal_padding
F_printf "[${tGRN} HI${tCLR} ] ${tYEL}===== Welcome to the wicens Email setup wizard =====${tCLR} E||e to exit"
if [ "$selection" = '1f' ] && [ "$amtm_import" = 1 ] ; then
F_terminal_warning
F_terminal_show "amtm import enabled"
F_terminal_show "script will save your entries but will continue using amtm config"
fi
;;
esac
case "$test_mode" in
1)
F_terminal_padding
F_printf "[${tYEL}INFO${tCLR}] ${tYEL}===== Test Mode - Sending 1 test message =====${tCLR}"
;;
esac
case "$from_menu" in
1) F_terminal_padding ;;
esac
return 0
} # terminal_header
F_status() {
F_pg1() {
update_rem=$((update_period - update_diff))
clear
F_printf "${tYEL}============================ wicens status page 1/2=============================${tCLR}"
F_terminal_padding
F_status_grn "Current saved WAN IP" "$saved_wan_ip"
F_status_grn "Current Email send to address" "$user_send_to_addr"
F_status_grn "Current Email send to CC address" "$user_send_to_cc"
F_status_grn "Current Email server addr:port" "$user_smtp_server"
F_status_grn "Current Email send format type" "$user_message_type"
F_status_grn "Current Email login address" "$user_login_addr"
F_status_grn "Current Email from address" "$user_from_addr"
F_status_grn "Current Email msg from name" "$user_email_from"
F_status_grn "Current Email msg to name" "$user_msg_to"
[ "$build_entry" = 1 ] && return 0
[ -f "$cred_loc" ] && F_status_grn "Current Email password" "Password saved"
[ "$user_message_type" = "smtp_ssl" ] && F_status_grn "Current Email protocol" "$protocol"
[ -n "$ssl_flag" ] && F_status_grn "SSL flag set" "$ssl_flag"
F_terminal_separator
if [ -n "$user_custom_subject" ] ; then
user_custom_subject_show="$user_custom_subject_decoded"
[ ${#user_custom_subject_show} -gt 31 ] && user_custom_subject_show="$(F_printfstr "$user_custom_subject_decoded" | awk '{print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom WAN IP Subject line set" "$user_custom_subject_show"
fi
if [ -n "$user_custom_subject_r" ] ; then
user_custom_subject_show="$user_custom_subject_r_decoded"
[ ${#user_custom_subject_show} -gt 31 ] && user_custom_subject_show="$(F_printfstr "$user_custom_subject_r_decoded" | awk '{print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom Reboot Subject line set" "$user_custom_subject_show"
fi
if [ -n "$user_custom_subject_f" ] ; then
user_custom_subject_show="$user_custom_subject_f_decoded"
[ ${#user_custom_subject_show} -gt 31 ] && user_custom_subject_show="$(F_printfstr "$user_custom_subject_f_decoded" | awk '{print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom Firmware Subject line set" "$user_custom_subject_show"
fi
if [ -n "$user_custom_subject_s" ] ; then
user_custom_subject_show="$user_custom_subject_s_decoded"
[ ${#user_custom_subject_show} -gt 31 ] && user_custom_subject_show="$(F_printfstr "$user_custom_subject_s_decoded" | awk '{print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom Update Subject line set" "$user_custom_subject_show"
fi
if [ -n "$user_custom_text" ] ; then
user_custom_text_show="$user_custom_text_decoded"
[ ${#user_custom_text_show} -gt 35 ] && user_custom_text_show="$(F_printf "$user_custom_text_decoded" | awk 'NR==1 {print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom WAN IP message text is set" "$user_custom_text_show"
fi
if [ -n "$user_custom_text_r" ] ; then
user_custom_text_show="$user_custom_text_r_decoded"
[ ${#user_custom_text_show} -gt 35 ] && user_custom_text_show="$(F_printf "$user_custom_text_r_decoded" | awk 'NR==1 {print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom Reboot message text is set" "$user_custom_text_show"
fi
if [ -n "$user_custom_text_f" ] ; then
user_custom_text_show="$user_custom_text_f_decoded"
[ ${#user_custom_text_show} -gt 35 ] && user_custom_text_show="$(F_printf "$user_custom_text_f_decoded" | awk 'NR==1 {print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom Firmware message text is set" "$user_custom_text_show"
fi
if [ -n "$user_custom_text_s" ] ; then
user_custom_text_show="$user_custom_text_s_decoded"
[ ${#user_custom_text_show} -gt 35 ] && user_custom_text_show="$(F_printf "$user_custom_text_s_decoded" | awk 'NR==1 {print substr($0, 1, 33)}' | /bin/sed 's/$/.../g')"
F_status_grn "Custom Update message text is set" "$user_custom_text_show"
fi
if [ -n "$user_custom_script_decoded" ] ; then
user_custom_script_show="$user_custom_script_decoded"
[ ${#user_custom_script_show} -gt 35 ] && user_custom_script_show="$(F_printfstr "$user_custom_script_decoded" | awk '{print substr($0,length($0)-33)}' | /bin/sed 's/^/.../g')"
F_status_grn "Custom script path" "$user_custom_script_show"
fi
[ -n "$user_script_call_time" ] && F_status_grn "Custom script call time" "$user_script_call_time"
F_status_grn "Cron run interval" "${cron_check_freq} minutes"
F_status_grn "Number of cron checks" "$cron_run_count"
F_status_grn "Number of wan-event checks" "$wancall_run_count"
F_status_grn "Total IP changes" "$ip_change_count"
F_status_grn "Last IP change" "$last_ip_change"
F_status_grn "Last ran with wan-event" "$last_wancall_run"
F_status_grn "Last monitored with cron" "$last_cron_run"
F_status_grn "Script configured date" "$created_date"
F_status_grn "Current saved WAN IP recorded" "$saved_wan_date"
F_status_grn "Current saved WAN IP lease age" "$(F_calc_lease | sed 's/^[[:space:]]*//')"
F_uptime
F_status_grn "Current router uptime" "$(F_printfstr "$uptime_pretty" | sed 's/^[[:space:]]*//')"
F_status_grn "Script last updated date" "$update_date"
F_status_grn "Script install date" "$install_date"
[ "$user_update_notification" = 1 ] && [ "$update_avail" = 'none' ] && F_status_grn "Secs to next update check w/cron" "$update_rem"
F_terminal_separator
F_terminal_padding
[ "$count_entry" = 1 ] && return 0
F_terminal_check "Any key - next page E||e to return to Main Menu"
read -rsn1 pg1wait
case $pg1wait in
E|e) F_clean_exit reload ;;
*) F_pg2 ;;
esac
} # pg1
F_pg2() {
clear
F_printf "${tYEL}============================ wicens status page 2/2=============================${tCLR}"
F_terminal_padding
if [ "$user_wanip_monitor" = 1 ]
then F_status_enabled "WAN IP change monitoring"
else F_status_disabled "WAN IP change monitoring"
fi
if [ "$user_wanip_notification" = 1 ]
then F_status_enabled "WAN IP change Email notify"
else F_status_disabled "WAN IP change Email notify"
fi
if [ "$user_reboot_notification" = 1 ]
then F_status_enabled "Router reboot Email notify"
else F_status_disabled "Router reboot Email notify"
fi
if [ "$user_fw_update_notification" = 1 ]
then F_status_enabled "Firmware update Email notify"
else F_status_disabled "Firmware update Email notify"
fi
if [ "$user_update_notification" = 1 ]
then F_status_enabled "Script update Email notify"
else F_status_disabled "Script update Email notify"
fi
F_terminal_separator
if [ "$amtm_import" = 1 ]
then F_status_enabled "Sync from amtm Email config"
else F_status_disabled "Sync from amtm Email config"
fi
if [ "$status_amtm" = 1 ]
then F_status_pass "amtm valid Email config test"
else F_status_fail "amtm valid Email config test"
fi
if [ "$status_email_cfg" = 1 ]
then F_status_pass "Loaded Email settings config test"
else F_status_fail "Loaded Email settings config test"
fi
F_terminal_separator
if [ "$fw_sw_mode" = 1 ] ; then
if F_wan_event check
then F_status_pass "wan-event entry test"
else F_status_fail "wan-event entry test"
fi
else
F_terminal_show "$(printf "%s%s|\n" "wan-event entry test" "$(printf '%*s' "$((35 - 20))" | tr ' ' '-')") ${tRED}Disabled - Not in router mode${tCLR}"
fi
if F_cru check
then F_status_pass "cron(cru) entry test"
else F_status_fail "cron(cru) entry test"
fi
if F_serv_start check
then F_status_pass "services-start cron(cru) entry test"
else F_status_fail "services-start cron(cru) entry test"
fi
if F_notify_reboot check status
then F_status_pass "services-start reboot entry test"
else F_status_fail "services-start reboot entry test"
fi
if F_notify_firmware check status
then F_status_pass "update-notification fw entry test"
else F_status_fail "update-notification fw entry test"
fi
F_terminal_separator
F_status_grn "Config file versions" "User: v$build_settings_version Core: v$update_settings_version"
[ "$update_avail" != 'none' ] && [ "$update_avail" != 'hotfix' ] && F_status_grn "New version is available!" "Version $update_avail"
[ "$update_avail" != 'none' ] && [ "$update_avail" = 'hotfix' ] && F_status_grn "Hotfix update is available!" "Hotfix for v$script_version"
F_status_grn "Script TTY lock age" "${tGRN}$(( $(F_date s) - $(/bin/sed -n '3p' /tmp/wicens_lock.tty) )) secs${tCLR}"
F_terminal_separator
[ "$status_email_cfg" = 0 ] && F_printf "$fail_reason"
F_terminal_padding
F_terminal_check "Any key - previous page E||e to return to Main Menu"
read -rsn1 pg2wait
case $pg2wait in
E|e) F_clean_exit reload ;;
*) F_pg1 ;;
esac
}
F_pg1
return 0
} # status
F_config_verbose() {
F_conf_pg1(){
clear
F_printf "${tYEL}===== Verbose config file status - User Config - 1/2 =====${tCLR}"
while IFS= read -r fileline ; do
if F_printfstr "$fileline" | grep -Fq '=' ; then
config_var="$(F_printfstr "$fileline" | cut -d'=' -f1)"
value=$(F_printfstr "$fileline" | cut -d'=' -f2 | tr -d "'" | sed 's/#.*//') # trim var comments
F_status_grn "$config_var" "$value"
fi
done < "$config_src"
F_terminal_separator
F_terminal_check "Any key - next page E||e to return to Main Menu"
read -rsn1 pg1wait
case $pg1wait in
E|e) F_clean_exit reload ;;
*) F_conf_pg2 ;;
esac
}
F_conf_pg2() {
clear
F_printf "${tYEL}===== Verbose config file status - Core Config - 2/2 =====${tCLR}"
while IFS= read -r fileline ; do
if F_printfstr "$fileline" | grep -Fq '=' ; then
config_var="$(F_printfstr "$fileline" | cut -d'=' -f1)"
value=$(F_printfstr "$fileline" | cut -d'=' -f2 | tr -d "'" | sed 's/#.*//') # trim var comments
F_status_grn "$config_var" "$value"
fi
done < "$update_src"
F_terminal_separator
F_terminal_check "Any key - previous page E||e to return to Main Menu"
read -rsn1 pg1wait
case $pg1wait in
E|e) F_clean_exit reload ;;
*) F_conf_pg1 ;;
esac
}
F_conf_pg1
} # config_verbose
F_main_menu() {
F_terminal_header
F_printf " ${tYEL}Option Select Status${tCLR}"
F_terminal_separator
if [ "$status_amtm" = 1 ] && [ "$amtm_import" = 1 ] ; then F_menu_enabled "amtm Email config sync-------| 0 "
elif [ "$status_amtm" = 1 ] && [ "$amtm_import" = 0 ] && [ "$status_email_cfg" = 1 ] ; then F_menu_disabled "amtm Email config sync-------| 0 "
elif [ "$status_amtm" = 0 ] && [ "$amtm_import" = 0 ] ; then F_terminal_show "amtm Email config sync-------| 0 ${tRED}Disabled - amtm not configured${tCLR}"
elif [ "$status_amtm" = 1 ] && [ "$amtm_import" = 0 ] && [ "$status_email_cfg" = 0 ] ; then F_terminal_show "amtm Email config sync-------| 0 ${tRED}Disabled -${tCLR} ${tGRN}Available${tCLR}"
fi
case "$status_email_cfg" in
1) F_menu_enabled "Create/Edit Email settings---| 1 " ;;
0) F_terminal_show "Create/Edit Email settings---| 1 ${tRED}Disabled - V||v to view errors${tCLR}" ;;
esac
case "$status_wanipmon" in
1) F_menu_enabled "WAN IP change monitor--------| 2 " ;;
0) F_menu_disabled "WAN IP change monitor--------| 2 " ;;
esac
case "$status_wanip" in
1) F_menu_enabled "WAN IP change Email notify---| 3 " ;;
0) F_menu_disabled "WAN IP change Email notify---| 3 " ;;
esac
case "$status_reboot" in
1) F_menu_enabled "Router reboot Email notify---| 4 " ;;
0) F_menu_disabled "Router reboot Email notify---| 4 " ;;
esac
case "$status_fw" in
1) F_menu_enabled "Firmware update Email notify-| 5 " ;;
0) F_menu_disabled "Firmware update Email notify-| 5 " ;;
esac
case "$status_update" in
1) F_menu_enabled "Script update Email notify---| 6 " ;;
0) F_menu_disabled "Script update Email notify---| 6 " ;;
esac
if [ -n "$user_custom_script" ]
then F_terminal_show "WAN IP change script---------| 7 ${tGRN}Enabled${tCLR} - Action ${tGRN}$user_script_call_time${tCLR}"
else F_menu_disabled "WAN IP change script---------| 7 "
fi
if [ -n "$user_custom_text" ] || [ -n "$user_custom_text_r" ] || [ -n "$user_custom_text_f" ] || [ -n "$user_custom_text_s" ]
then F_menu_enabled "Custom Email text menu-------| 8 "
else F_menu_disabled "Custom Email text menu-------| 8 "
fi
if [ -n "$user_custom_subject" ] || [ -n "$user_custom_subject_r" ] || [ -n "$user_custom_subject_f" ] || [ -n "$user_custom_subject_s" ]
then F_menu_enabled "Custom Email subjects--------| 9 "
else F_menu_disabled "Custom Email subjects--------| 9 "
fi
F_terminal_separator
F_terminal_show "View current status/settings-| V||v"
F_terminal_show "Force WAN IP compare w/script| M||m"
F_terminal_show "Show sample WAN IP Email-----| S||s"
F_terminal_show "Send a test Email------------| T||t"
F_terminal_show "Show last Email curl log-----| L||l"
F_terminal_show "Show script log--------------| Z||z"
F_terminal_show "Reset cron/wan-event counts--| N||n"
F_terminal_show "Reset script to default------| R||r"
F_terminal_show "Toggle terminal color on/off-| C||c"
F_terminal_show "Uninstall script-------------| U||u"
if [ "$status_email_cfg" = 0 ] && [ -f "$script_backup_file" ]
then F_terminal_show "Backup Email config----------| B||b ${tGRN}Backup Found - select to restore${tCLR}"
else F_terminal_show "Backup/Restore settings menu-| B||b"
fi
if [ "$update_avail" != 'none' ] && [ "$update_avail" != 'hotfix' ] ; then F_terminal_show "Install script update--------| I||i ${tGRN}Update available - version $update_avail${tCLR}"
elif [ "$update_avail" != 'none' ] && [ "$update_avail" = 'hotfix' ] ; then F_terminal_show "Install script update--------| I||i ${tGRN}Hotfix available!${tCLR}"
else F_terminal_show "Check for script update------| F||f"
fi
F_terminal_show "Other options----------------| H||h"
F_terminal_show "About script-----------------| A||a"
F_terminal_show "Exit-------------------------| E||e"
[ "$from_menu" = 0 ] && stop_time="$(awk '{print $1}' < /proc/uptime)"
load_time="$(F_printf "$start_time $stop_time" | awk '{diff = $2 - $1; if (diff >= 10) printf "10s+"; else printf "%.2f", diff}')"
F_printf "[${tGRN}${load_time}${tCLR}] Menu load time"
case "$1" in
'hidden') F_terminal_padding ; F_opt_about | sed -n '93,101p' ;;
esac
F_terminal_padding
F_terminal_check "Selection : "
selection=''
from_menu=1
read -r selection
F_terminal_erase
case "$selection" in
0) F_amtm ;;
1) if [ "$status_email_cfg" = 1 ] ; then
F_edit_settings
else
F_build_settings
fi
;;
'1f'|'1F') source "$config_src" ; F_build_settings ;;
2) F_wanip_monitor ; F_menu_exit ;;
3) F_notify_wanip ;;
4) F_notify_reboot ;;
5) F_notify_firmware ;;
6) F_notify_update ;;
7) until F_opt_script ; do : ; done ; F_menu_exit ;;
8) until F_opt_text_select ; do : ; done ; F_menu_exit ;;
9) until F_opt_subject_select ; do : ; done ; F_menu_exit ;;
a|A) F_opt_about ; F_menu_exit ;;
b|B) F_opt_backup_restore ;;
c|C) F_opt_color ;;
e|E) F_clean_exit ;;
f|F) F_web_update_check force ;;
i|I)
case "$update_avail" in
'none') printf "%b %s is an invalid entry, any key to retry" "$tCHECKFAIL" "$selection" ; read -rsn1 ; return 1 ;;
*) F_local_script_update ;;
esac
;;
l|L) F_opt_mail_log ;;
m|M)
if ! F_compare ; then
building_settings=1
F_script_wan_update
building_settings=0
fi
F_menu_exit
;;
n|N) F_opt_count ;;
r|R) F_opt_reset ;;
s|S) F_opt_sample ;;
t|T) until F_opt_test ; do : ; done ; F_menu_exit ;;
u|U) F_opt_uninstall ;;
v|V) F_status && F_menu_exit ;;
z|Z)
if [ -f "$script_log_loc" ] ; then
clear
cat "$script_log_loc"
else
F_terminal_check_fail "/jffs/addons/wicens/wicens.log does not exist"
fi
F_menu_exit
;;
vv|VV) F_config_verbose ;;
fr) F_replace_var update_avail 'none' "$update_src" ; F_replace_var update_notify_state 0 "$update_src" ; F_replace_var update_cron_epoch 0 "$update_src" ; F_terminal_check_ok "Reset any found script updates" ; F_menu_exit ;;
fl) [ -f "$mail_log" ] && rm -f "$mail_log" && F_terminal_check_ok "Reset Email curl/sendmail log output" ; F_menu_exit ;;
ul) [ -f "$user_script_log" ] && clear && cat "$user_script_log" ; F_menu_exit ;;
fe) F_email_eg ;;
rc) F_default_update_create ; config_updated=1 ; fw_nvram_check_diff=666 ; source "$update_src" ; F_terminal_check_ok "wicens update(core) config reset" ; F_firmware_check ; F_menu_exit ;;
ri) F_replace_var saved_wan_ip '' "$config_src" ; F_terminal_check_ok "Removed saved WAN IP" ; F_menu_exit ;;
dw)
case "$dual_wan_check" in
1)
F_replace_var dual_wan_check 0 "$update_src"
F_log_terminal_ok "Dual WAN check disabled"
;;
0)
F_replace_var dual_wan_check 1 "$update_src"
F_log_terminal_ok "Dual WAN check enabled"
;;
esac
F_menu_exit
;;
h|H) from_menu=2 ; F_main_menu hidden ;;
*)
from_menu=2
[ -n "$selection" ] && F_terminal_check_fail "${tRED}$selection${tCLR} is an invalid selection, any key to retry" && read -rsn1
return 1
;;
esac
} # main menu
# SCRIPT LOCK #########################################################################################################
#######################################################################################################################
F_lock() {
case "$run_option" in
'cron'|'tty')
if [ -f '/tmp/wicens_lock.tty' ] ; then
lock_pid="$(sed -n '2p' "/tmp/wicens_lock.tty")"
lock_epoch="$(sed -n '3p' "/tmp/wicens_lock.tty")"
lock_age="$(($(F_date s) - lock_epoch))"
if [ ! -d "/proc/$lock_pid" ] ; then # if tty lock exists but not running remove
rm -f '/tmp/wicens_lock.tty'
[ -f '/tmp/wicens_internetlock.tty' ] && rm -f '/tmp/wicens_internetlock.tty' && F_log "Error - Removed tty internet lock, process non-existent"
F_terminal_header exit
F_log_show "Error - Removed tty lock - Lock age: ${lock_age}s PID: (${lock_pid}) non-existent "
else
if [ "$lock_age" -gt 1800 ] ; then # if terminal has been running for 30 mins kill it and continue
kill -9 "$lock_pid" 2> /dev/null
rm -f '/tmp/wicens_lock.tty'
F_terminal_header exit
F_log_terminal_fail "Error - Removed tty lock - Lock age: ${lock_age}s - Killed PID: ${lock_pid}"
else
# prevent cron while in tty
F_printfstr "[FAIL] Running in terminal session - Lock age: ${lock_age}s - PID: ${lock_pid}"
[ "$run_option" = 'cron' ] && exit 0
fi
fi
[ "$run_option" = 'tty' ] && F_wait 20
fi
# check age of all call types and clean up with cron/tty, prevent cron from running while other valid call is running
for lockfile in fwupdate wancall reboot send cron ; do
if [ ! -f "/tmp/wicens_lock.${lockfile}" ] ; then
[ -f "/tmp/wicens_internetlock.${lockfile}" ] && rm -f "/tmp/wicens_internetlock.${lockfile}"
else
lock_pid="$(sed -n '2p' "/tmp/wicens_lock.$lockfile")"
lock_epoch="$(sed -n '3p' "/tmp/wicens_lock.$lockfile")"
lock_age="$(($(F_date s) - lock_epoch))"
if [ -z "$lock_pid" ] || [ -z "$lock_epoch" ] || [ -z "$lock_age" ] ; then
rm -f "/tmp/wicens_lock.$lockfile"
F_log "Error - found /tmp/wicens_lock.${lockfile} but file missing pid/epoch, removed"
else
if [ "$lock_age" -gt 180 ] ; then
if [ -d "/proc/$lock_pid" ] ; then
# internet check can run longer than lock_age_max check if thats what the old process is doing
if [ -f "/tmp/wicens_internetlock.$lockfile" ] ; then
internetlock_age="$(sed -n '1p' "/tmp/wicens_internetlock.$lockfile")"
if [ "$(($(F_date s) - internetlock_age))" -gt 315 ] ; then
kill -9 "$lock_pid" 2> /dev/null
rm -f "/tmp/wicens_lock.$lockfile"
rm -f "/tmp/wicens_internetlock.$lockfile"
F_log_terminal_fail "Error - found wicens_lock.${lockfile} ${lock_age}s and internet lock ${internetlock_age}s, killed process ${lock_pid} and removed locks"
else
F_log_terminal_fail "Error - found wicens_lock.${lockfile} ${lock_age}s and internet_lock ${internetlock_age}s, internet lock not over age limit(5 mins)... exiting"
exit 0
fi
else
kill -9 "$lock_pid" 2> /dev/null
rm -f "/tmp/wicens_lock.${lockfile}" 2> /dev/null
F_log_terminal_fail "Error - Killed process pid ${lock_pid} started by ${lockfile} over age limit(180) ${lock_age}"
fi
else
F_log_terminal_fail "Error - Process doesn't exit - process lock age: ${lock_age} secs Max:180, removing lock"
rm -f "/tmp/wicens_lock.${lockfile}" 2> /dev/null
[ -f "/tmp/wicens_internetlock.$lockfile" ] && rm -f "/tmp/wicens_internetlock.$lockfile"
fi
else
# prevent cron from running while any other valid automated call is running
F_terminal_header
F_terminal_warning
F_log_terminal_fail "Script already running - locked by ${lockfile} pid ${lock_pid} running ${lock_age} secs"
F_log_show "$((180 - lock_age)) secs remaining till lock purge possible if necessary"
[ "$run_option" = 'cron' ] && exit 0
[ "$run_option" = 'tty' ] && F_menu_exit
fi
fi
fi
done
;;
*)
if [ -f "wicens_lock.${run_option}" ] ; then
lock_pid="$(sed -n '2p' "/tmp/wicens_lock.$run_option")"
lock_epoch="$(sed -n '3p' "/tmp/wicens_lock.$run_option")"
lock_age="$(($(F_date s) - lock_epoch))"
F_log "Error - lock file exists for this call type Aged:${lock_age}secs max:180 PID:$lock_pid"
exit 2
fi
;;
esac
{
F_printfstr "$run_option"
F_printfstr "$$"
F_printfstr "$(F_date s)"
F_printfstr "$(F_date r)"
} > "$script_lock"
return 0
} # lock
F_ntp() {
ntp_lock="/tmp/wicens_ntplock.$run_option"
[ -f "$ntp_lock" ] && exit 0 # script already running waiting on NTP sync
F_uptime
case "$(F_nvram ntp_ready)" in
1) ;;
*) # if ntp nolonger synced but up greater than a day warn user
if [ "$router_uptime" -gt 86400 ] ; then
F_log_terminal_fail "script failed to start, current time may be correct"
F_log_terminal_fail "but your your NTP is NOT synced and router uptime >1 day"
F_log_show "Please check your NTP configuration"
exit 1 # script lock not yet created
fi
F_printfstr "$(F_date s) $$" > "$ntp_lock"
ntp_wait_time=0
F_log_show "NTP is not synced, waiting upto 600 seconds (10min) checking every 3 seconds for NTP sync"
while [ "$(F_nvram ntp_ready)" -ne 1 ] && [ "$ntp_wait_time" -lt 600 ] ; do
ntp_wait_time="$((ntp_wait_time + 3))"
printf '\r%b Elapsed time : %s secs' "$tTERMHASH" "$ntp_wait_time"
sleep 3
printf '%b' "$tERASE"
done
if [ "$ntp_wait_time" -ge 600 ] ; then
F_log_show "NTP failed to sync and update router time after 10 mins of checking"
F_log_show "Please check your NTP configuration"
F_clean_exit
fi
rm -f "$ntp_lock"
# ntp_ready can be set but just let settle
sleep 5
;;
esac
TZ="$(cat /etc/TZ)"
export TZ
run_date="$(F_date f)"
run_epoch="$(F_date s)"
# lock script from duplicate runs
F_lock
# time is set load user settings
F_user_settings
# if auto run check Script eg amtm enabled - any notification enabled - but they delete their amtm config we'll spam the log
case "$1" in
'noterminal') F_ready_check ;;
esac
return 0
} # ntp
# FIRST SCRIPT COMMANDS ###############################################################################################
#######################################################################################################################
#######################################################################################################################
case "$run_option" in
'reload') # reload menu without ntp/lock/alias/fw check etc
run_date="$(F_date r)"
run_epoch="$(F_date s)"
run_option='tty'
script_lock="/tmp/wicens_lock.$run_option"
F_user_settings
until F_main_menu ; do : ; done
;;
'tty') # only check alias/FW ver with terminal runs
F_ntp
F_firmware_check
F_alias # installed with F_firmware_check, checked here (sanity check)
# if Email send failed we need to clear out the file for future
if [ -f "$wicens_wanip_retry" ] || [ -f "$wicens_fw_retry" ] || [ -f "$wicens_update_retry" ] || [ -f "$wicens_send_retry" ] || [ -f "$wicens_reboot_retry" ] ; then
F_terminal_header
F_terminal_show "A failed Email retry file exists... removing"
F_terminal_padding
for file_remove in "$wicens_wanip_retry" "$wicens_fw_retry" "$wicens_reboot_retry" "$wicens_send_retry" "$wicens_update_retry"
do
[ -f "$file_remove" ] && cat "$file_remove" && F_terminal_padding && rm -f "$file_remove"
done
F_wait 60
fi
# start wicens menu
until F_main_menu ; do : ; done
;;
'uninstall'|'-uninstall'|'--uninstall')
run_option='tty'
F_ntp
F_opt_uninstall
;;
'help'|'-help'|'--help'|'-h'|'--h') F_opt_about ;;
##### auto-run options ############################################################################################
# exit needed in all but cron so it can fall through every call type check
'wancall') # wan-event call
F_ntp noterminal
new_wancall_count="$((wancall_run_count + 1))"
F_log_show "Started by 'wan-event connected' trigger, sleeping $wan_event_wait seconds before running IP compare"
F_replace_var wancall_run_count "$new_wancall_count" "$config_src"
F_replace_var last_wancall_run "$run_date" "$config_src"
sleep "$wan_event_wait" # let connection settle before checking anything
# if called by wancall ensure we start fresh 5 attempts
[ -f "$wicens_wanip_retry" ] && rm -f "$wicens_wanip_retry"
if ! F_compare ; then
if [ "$user_wanip_notification" = 1 ] ; then
F_wanip_email_msg
else
F_script_wan_update
fi
fi
F_clean_exit
;;
'reboot') # router reboot call
F_ntp noterminal
[ -f "$wicens_reboot_retry" ] && rm -f "$wicens_reboot_retry" # should never execute but due diligence
F_log_show "Started by services-start, reboot detected, sending reboot notification in $reboot_notify_wait seconds"
# set 1 at start of attempt set to 0 by F_reboot_email_msg on msg success and checked by cron
F_replace_var reboot_notify_state 1 "$update_src"
F_reboot_email_msg
F_clean_exit
;;
'fwupdate') # firmware update call
F_ntp noterminal
# called by update-notification event
F_uptime && [ "$router_uptime" -lt 600 ] && sleep 60 # router up less than 10 mins wait 1 mins before sending
[ -f "$wicens_fw_retry" ] && rm -f "$wicens_fw_retry" # if retry file exists remove, we were called by update-notification again
F_log_show "Started by update-notification trigger, sending firmware update notification"
# set 1 at start of attempt set to 0 by F_fw_update_email_msg msg success and checked by cron
F_replace_var fw_notify_state 1 "$update_src"
F_fw_update_email_msg
F_clean_exit
;;
'send') # called as email forwarder
F_ntp noterminal
fwd_send_msg="$2"
fwd_send_addr="$3"
if [ -z "$fwd_send_msg" ] ; then
F_log_show "Error, script called as forwarder but no Email message defined"
F_clean_exit fail
elif [ ! -f "$fwd_send_msg" ] ; then
F_log_show "Error, script called as forwarder but can't find $fwd_send_msg Email message"
F_clean_exit fail
fi
if [ -n "$fwd_send_addr" ] ; then
F_log_terminal_ok "script started as forwarder, attempting to send $fwd_send_msg to $fwd_send_addr"
else
F_log_terminal_ok "script started as forwarder, attempting to send $fwd_send_msg to $user_send_to_addr"
fi
if F_opt_forward ; then
F_clean_exit
else
F_clean_exit fail
fi
;;
'cron') # cron call
# router up less than 10 mins don't execute cron check
F_uptime && [ "$router_uptime" -lt 600 ] && exit 0
F_ntp noterminal
[ "$cron_option" = 0 ] && F_clean_exit # update_conf allows disabling cron checks but keeps cron entries
F_replace_var cron_run_count "$((cron_run_count + 1))" "$config_src"
F_replace_var last_cron_run "$run_date" "$config_src"
[ "$(wc -c "$script_log_loc" | cut -d' ' -f1)" -gt 200000 ] && F_printfstr "$(F_date f) Log file grew to 200KB file was reset" > "$script_log_loc"
# cron - Sunday logging 6pm ###################################################################################
weekly_wancall_total=$((wancall_run_count - last_wancall_log_count)) # log msg count
if [ "$(/bin/date +'%u')" = 7 ] && [ "$log_cron_msg" = 1 ] && [ "$(/bin/date +'%H')" = 18 ] ; then
F_log "Started successfully by wan-event connected $weekly_wancall_total times in the last week, $wancall_run_count times since $created_date"
F_log "Last wan-event connected trigger $last_wancall_run"
F_log "Recorded $ip_change_count IP change(s) since install"
F_uptime && F_log "Router uptime $uptime_pretty"
F_replace_var last_wancall_log_count "$wancall_run_count" "$config_src"
F_replace_var log_cron_msg 0 "$config_src"
fi
if [ "$(/bin/date +'%u')" = 1 ] && [ "$log_cron_msg" = 0 ] ; then # monday reset
F_replace_var log_cron_msg 1 "$config_src"
fi
# cron - update check #########################################################################################
if [ "$user_update_notification" = 1 ] && [ "$update_avail" = 'none' ] ; then # if update already found dont recheck
update_cron_diff=$((run_epoch - update_cron_epoch))
if [ "$update_cron_diff" -ge "$update_period" ] ; then # check for webupdate every 48hours
sleep "$(F_random_num 15)" # good internet neighbor
F_web_update_check
F_replace_var update_cron_epoch "$(F_date s)" "$update_src"
fi
fi
# cron - update notification initial attempt and retry if 'cron update check' found an update #################
# set notify_state 1 on success, reset with upgrade
if [ "$update_avail" != 'none' ] && [ "$update_notify_state" = 0 ] && [ "$user_update_notification" = 1 ] ; then # no notification yet sent for update & enabled
if [ -f "$wicens_update_retry" ] ; then # set 5 time retry, retry reset in script_update_email_msg success
F_printfstr "# Attempting to send script update notification $(F_date r)" >> "$wicens_update_retry"
else
F_printfstr "# Attempting to send script update-notification $(F_date r)" > "$wicens_update_retry"
fi
if [ "$(wc -l < "$wicens_update_retry")" -le "$max_email_retry" ] ; then
F_internet_check update
if [ "$update_avail" = 'hotfix' ] ; then
F_log "Hotfix update for ver $script_version available, run manually to update"
else
F_log "Update to ver $update_avail available, run manually to update"
fi
F_log "Sending script update notification Email to ${user_send_to_addr}"
F_script_update_email_msg
else
F_log "Critical error, attempted to send script update Email $max_email_retry times, giving up"
F_replace_var update_notify_state 1 "$update_src" # set like we had success to only log error 1 time
fi
fi
# cron - fw update notification retry #########################################################################
# set 1 and retry created by initial fwupdate call, reset to 0 after success
if [ "$fw_notify_state" = 1 ] && [ -f "$wicens_fw_retry" ] ; then
source "$wicens_fw_retry"
# dont exit continue to forwarder/ipcheck
if [ "$(wc -l < "$wicens_fw_retry")" -le "$((max_email_retry + 2))" ] ; then # retry created in wicens fwupdate
F_fw_update_email_msg
else
# check age of retries if over reset and start over
wicens_fw_retry_age=$((run_epoch - wicens_fw_retry_time))
if [ "$wicens_fw_retry_age" -gt "$retry_wait_period" ] ; then
rm -f "$wicens_fw_retry"
F_fw_update_email_msg
fi
fi
fi
# cron - reboot notification retry ############################################################################
# set 1 and retry created by initial reboot call, reset to 0 after success
if [ "$reboot_notify_state" = 1 ] && [ -f "$wicens_reboot_retry" ] ; then
source "$wicens_reboot_retry"
if [ "$(wc -l < "$wicens_reboot_retry")" -le "$((max_email_retry + 2))" ] ; then # retry created in reboot_email
F_reboot_email_msg
else
wicens_reboot_retry_age=$((run_epoch - wicens_reboot_retry_time))
if [ "$wicens_reboot_retry_age" -gt "$retry_wait_period" ] ; then
rm -f "$wicens_reboot_retry"
F_reboot_email_msg
fi
fi
fi
# cron - wicens forwarder retry ###############################################################################
if [ -f "$wicens_send_retry" ] ; then # retry created in F_opt_forward
source "$wicens_send_retry" # source as retry needs msg/sendto/retrytime
if [ "$(wc -l < "$wicens_send_retry")" -le "$((max_email_retry + 4))" ] ; then # retry for forwarder has 4 lines coded
F_opt_forward
else
wicens_send_retry_age=$((run_epoch - wicens_send_retry_time))
if [ "$wicens_send_retry_age" -gt "$retry_wait_period" ] ; then # email failed 5 times w/internet up, after 6 hrs try again
rm -f "$wicens_send_retry" # remove to refresh retries
F_opt_forward
fi
fi
fi
# cron - wanip notify #########################################################################################
# cron - wicens IP check ##################################################################################
if [ "$user_wanip_monitor" = 1 ] ; then
if ! F_compare ; then
if [ -f "$wicens_wanip_retry" ] ; then
if [ "$(wc -l < "$wicens_wanip_retry")" -ge "$((max_email_retry + 2))" ] ; then
source "$wicens_wanip_retry"
wicens_wanip_retry_age=$((run_epoch - wicens_wanip_retry_time))
if [ "$wicens_wanip_retry_age" -gt "$retry_wait_period" ] ; then
rm -f "$wicens_wanip_retry" # remove and refresh attempts fall through to F_wanip_email
else
F_clean_exit # done cron check exit
fi
fi
fi
if [ "$user_wanip_notification" = 1 ] ; then
F_wanip_email_msg # sets wicens_wanip_retry, clears on success
else
F_script_wan_update
fi
fi
fi
stop_time="$(awk '{print $1}' < /proc/uptime)"
F_printf "[${tGRN}$(F_printf "$start_time $stop_time" | awk '{diff = $2 - $1; if (diff >= 10) printf "9.99"; else printf "%.2f", diff}')${tCLR}] Cron run time"
F_clean_exit
;;
*)
F_terminal_check_fail "wicens.sh ${tRED}${run_option}${tCLR} is an invalid option"
F_terminal_padding
exit 0
;;
esac
########################################################################################################################
########################################################################################################################
# EOF