ignoreSubmodules = dirty
tool = meld
# gitinspector complained
-renamelimit = 5000
+#renamelimit = 5000
+renames = copy
[gitreview]
username = iank
shopt -s extglob
# include .files when globbing, but ignore files name . and ..
# setting this also sets dotglob.
-# Note, this doesnt work in bash 4.4 anymore, for paths with
-# more than 1 directory, like a/b/.foo, since * is fixed to not match /
-export GLOBIGNORE=*/.:*/..
+export GLOBIGNORE="*/.:*/.."
# broken with bash_completion package. Saw a bug for this once. dont anymore.
# still broken in wheezy
fi
}
+sgu() {
+ systemctl list-unit-files | rg "$@"
+}
-shellck() {
+sk() {
# 2086 = unquoted $var
# 2046 = unquoted $(cmd)
+ # 2068: Double quote array expansions to avoid re-splitting elements.
# i had -x as an arg, but debian testing(stretch) doesn\'t support it
- shellcheck -e 2086,2046,2068,2006,2119 "$@"
+ shellcheck -x -e 2086,2046,2068 "$@"
+ # had this before. not sure what it is 2119
}
skaraoke() {
# todo: if we cancel in the middle of a btrfs send, then run again immediately, the received subvolume doesn't get a Received UUID: field, and we won't mount it. Need to figure out a solution that will fix this.
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
source /usr/local/lib/err
# the wiki recommends 30 days or so, but
# it makes the comp lag like shit for a day,
# so I'm going with 90 days.
- if (( $date > `date +%s` - 60*60*24*30 )); then
+ if (( date > $(date +%s) - 60*60*24*30 )); then
echo "cron: skiping scrub of $mnt"
continue
fi
user=${domain_user[i+1]}
d=/etc/letsencrypt/live/$domain
- if [[ $RENEWED_LINEAGE == $d ]]; then
+ if [[ $RENEWED_LINEAGE == "$d" ]]; then
install -m 640 -g $user $d/{privkey.pem,fullchain.pem} $(eval echo ~$user)
exit 0
fi
# limitations under the License.
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
esac
done
-if [[ ! $@ ]]; then
+if [[ ! $1 ]]; then
echo "$0: error: expected mountpoint argument"
fi
d "svp=$svp # subvolume path"
snaps=($root_dir/btrbk/$subvol_dir.20*) # Assumes we are in the 21st century.
- if [[ ! ${snaps[@]} ]]; then
+ if [[ ! ${snaps[*]} ]]; then
# no snapshots yet
echo "$0: warning: no snapshots found at $root_dir/btrbk/$subvol_dir.20*. this is expected for a brand new volume"
continue
targets=( "$2"/!(.git|..|.) )
else
for f in "$1"/!(.git|..|.); do
- [[ -d $f ]] && targets+=("$f") ||:
+ if [[ -d $f ]]; then targets+=("$f"); fi
done
fi
- local below="$( readlink -f "$root/..")"
+ local below
+ below="$( readlink -f "$root/..")"
for path in "${targets[@]}"; do
- local fullpath="$(readlink -f "$path")"
+ local fullpath
+ fullpath="$(readlink -f "$path")"
#e $fullpath $below # debug
if [[ -f $path || $(dirname $(readlink -f "$fullpath")) == "$below" ]]; then
m lnf -T "$path" "$HOME/${path#$root/}"
common-file-setup() {
- local dir fs x bdir f dst
+ local dir fs x f
for dir in "$@"; do
fs=$dir/filesystem
if [[ -e $fs && $user =~ ^iank?$ ]]; then
/p/c/filesystem/etc/openvpn/easy-rsa/keys/*.key
/p/c/machine_specific/kw/filesystem/etc/openvpn/client/*.key
)
- if [[ -e $files ]]; then
+ if [[ -e ${files[0]} ]]; then
chmod 600 ${files[@]}
fi
# p needs to go first so .ssh link is created, then config link inside it
sudo bash -c 'shopt -s nullglob; cd /etc/openvpn; for f in client/* server/*; do ln -sf $f .; done'
- m sudo -H -u user2 "$BASH_SOURCE"
+ m sudo -H -u user2 "${BASH_SOURCE[0]}"
;;
user2)
m common-file-setup ${c_dirs[@]}
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
xout="$(xrandr)"
xe() { echo "$xout"; }
-x=$(xe | grep -E '^(DisplayPort-[0123]|DVI-0|DP-[1234]|DVI-I-1) connected' | wc -l)
+x=$(xe | grep -Ec '^(DisplayPort-[0123]|DVI-0|DP-[1234]|DVI-I-1) connected')
if (( x > 2 )); then
left=$(xe | sed -rn 's/^(DVI[^ ]+) connected .*/\1/p')
dps=( $(xe | sed -rn 's/^(DP-[01234]|DisplayPort-[01234]) connected .*/\1/p') )
##### variables/env setup
-script_dir="$(readlink -f "$BASH_SOURCE")"; script_dir=${script_dir%/*}
+script_dir="$(readlink -f "${BASH_SOURCE[@]}")"; script_dir=${script_dir%/*}
+# shellcheck source=./pkgs
source $script_dir/pkgs
set +x
source /a/bin/distro-functions/src/identify-distros
sudo systemctl start keyscriptoff.service
# from /usr/share/doc/dropbear-initramfs/README.initramfs.gz
- while read m _; do /sbin/modinfo -F filename "$m"; done </proc/modules | \
+ while read -r m _; do /sbin/modinfo -F filename "$m"; done </proc/modules | \
sed -nr "s@^/lib/modules/`uname -r`/kernel/drivers/net(/.*)?/([^/]+)\.ko\$@\2@p" \
| sudo dd of=/etc/initramfs-tools/modules
sudo apt-get -y install initramfs-tools-core
pi nfs-common
s dd of=/root/imount <<'EOF'
#!/bin/bash
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
for dir in /i /mnt/iroot /k /kr /w; do
### setup
source /a/bin/errhandle/err
-src="$(readlink -f -- "$BASH_SOURCE")"; src=${src%/*} # directory of this file
+src="$(readlink -f -- "${BASH_SOURCE[0]}")"; src=${src%/*} # directory of this file
+# shellcheck source=./pkgs
source $src/pkgs
set -x
simple_packages+=($@)
}
distro=$(distro-name)
+codename=$(debian-codename)
codename_compat=$(debian-codename-compat)
pending_reboot=false
sed="sed --follow-symlinks"
pi ${p1[@]}
##### begin automatic upgrades ####
-# this makes it so we upgrade everything
-s debconf-set-selections <<'EOF'
-unattended-upgrades unattended-upgrades/origins_pattern string "codename=${distro_codename}";
+
+s dd of=/etc/apt/apt.conf.d/10periodic <<'EOF'
+# this file was mostly just comments.
+APT::Periodic::Update-Package-Lists "1";
+APT::Periodic::Download-Upgradeable-Packages "1";
+APT::Periodic::AutocleanInterval "7";
+APT::Periodic::Unattended-Upgrade "1";
+EOF
+
+s dd of=/etc/apt/apt.conf.d/50unattended-upgrades <<EOF
+# fyi: default file has comments about available options,
+# you may want to read that.
+Unattended-Upgrade::Mail "root";
+Unattended-Upgrade::MailOnlyOnError "true";
+Unattended-Upgrade::Remove-Unused-Dependencies "true";
+Unattended-Upgrade::Origins-Pattern {
+ # default is just security updates.
+ "origin=*";
+};
EOF
-s dpkg-reconfigure -u -fnoninteractive unattended-upgrades
-# Setup daily reboots, so all unattended upgrades go into affect
-# unattended upgrades happen at 6 am + rand(60 min).
-echo '20 7 * * * root /usr/local/bin/zelous-unattended-reboot' | s dd of=/etc/cron.d/unattended-upgrade-reboot
+# Setup reboots when running outdated stuff, unattended upgrades happen
+# at 6 am + rand(60 min).
+/usr/local/bin/log-once checkrestart
+
+# old names, too verbose
+s rm -f /etc/cron.d/unattended-upgrade-reboot /usr/local/bin/zelous-unattended-reboot
+
+s dd of=/etc/cron.d/myupgrade <<'EOF'
+20 7 * * * root /usr/local/bin/myupgrade | /usr/local/bin/log-once -1 myupgrade
+0 * * * * root /usr/local/bin/mycheckrestart | /usr/local/bin/log-once -1 mycheckrestart
+EOF
##### end automatic upgrades ####
# office is not exposed to internet yet
# s reboot now
# when running docker-compose run, kernel stack traces are printed to the journal.
# things seem to succeed, google says nothing, so ignoring them.
- curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` | s dd of=/usr/local/bin/docker-compose
+ curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-$(uname -s)-$(uname -m) | s dd of=/usr/local/bin/docker-compose
s chmod +x /usr/local/bin/docker-compose
printf "%s=%s\n" $key "$(docker-compose run --rm web rake secret|dos2unix|tail -n1)" >>.env.production
done
found=false
- while read -r domain port pass; do
+ while read -r domain _ pass; do
if [[ $domain == mail.iankelling.org ]]; then
found=true
# remove the username part
# newer version needed for false positive in checkrestart
p install -y --allow-unauthenticated debian-goodies
+ s dd of=/etc/apt/preferences.d/shellcheck <<EOF
+Package: shellcheck
+Pin: release a=etiona
+Pin-Priority: 1005
+
+Package: shellcheck
+Pin: release a=etiona-updates
+Pin-Priority: 1005
+
+Package: shellcheck
+Pin: release a=etiona-security
+Pin-Priority: 1005
+EOF
+
+
;;
esac
# https://apt.syncthing.net/
curl -s https://syncthing.net/release-key.txt | sudo apt-key add -
s="deb http://apt.syncthing.net/ syncthing release"
- if [[ $(cat /etc/apt/sources.list.d/syncthing.list) != $s ]]; then
+ if [[ $(cat /etc/apt/sources.list.d/syncthing.list) != "$s" ]]; then
echo "$s" | s dd of=/etc/apt/sources.list.d/syncthing.list
p update
fi
####### begin misc packages ###########
+case $codename in
+ flidas)
+
+ ;;
+esac
+
+
# sakura config is owned by ian
reset-sakura
reset-konsole
s dpkg -i $t
rm $t
# this guesses at the appropriate directory, adjust if needed
-x=(/usr/lib/x86_64-linux-gnu/perl/5.*)
-sudo ln -sf ../../../perl/5.18.2/SPD/ $x
+perldir=(/usr/lib/x86_64-linux-gnu/perl/5.*)
+sudo ln -sf ../../../perl/5.18.2/SPD/ ${perldir[0]}
# newer distro had gpg2 as default, older one, flidas, need to make it that way
-x=$(which gpg2)
+gpgpath=$(which gpg2)
if [[ $x ]]; then
s mkdir -p /usr/local/spdhackfix
- s lnf -T $x /usr/local/spdhackfix/gpg
+ s lnf -T $gpgpath /usr/local/spdhackfix/gpg
fi
### end spd install
# on grub upgrade, we get prompts unless we do this
devs=()
for dev in $(s btrfs fil show /boot | sed -nr 's#.*path\s+(\S+)$#\1#p'); do
- devs+=($(devbyid $dev),)
+ devs+=("$(devbyid $dev),")
done
devs[-1]=${devs[-1]%,} # jonied by commas
s debconf-set-selections <<EOF
;;
esac
-case $distro in
- fedora) cabal install shellcheck ;;
- *) e shellcheck ;;
- # unknown for older ubuntu
-esac
-
case $distro in
arch|debian|trisquel|ubuntu) e pumpa ;;
# others unknown. do have a buildscript:
/usr/share/xscreensaver/xscreensaver-wrapper.sh &
fi
-if [[ $HOSTNAME == $MAIL_HOST ]]; then
- arbtt-capture --sample-rate=10 &
-fi
+# if [[ $HOSTNAME == $MAIL_HOST ]]; then
+# arbtt-capture --sample-rate=10 &
+# fi
# we run this cronjob along with sending the test email every 10
# minutes, so give it 2 minutes to arrive, then if there is an email at
# least 23 minutes old, the last 2 test emails have failed.
-if [[ ! $@ && $- != *i* ]]; then
+if [[ ! $1 && $- != *i* ]]; then
sleep 120
fi
rm -f /nocow/user/mailtest-failure
fi
-find -type f -mtime +1 -delete
+find . -type f -mtime +1 -delete
--- /dev/null
+#!/bin/bash
+# Copyright (C) 2019 Ian Kelling
+# SPDX-License-Identifier: AGPL-3.0-or-later
+if [ -z "$BASH_VERSION" ]; then echo "error: shell is not bash" >&2; exit 1; fi
+
+if [[ $EUID != 0 ]]; then s=sudo; fi
+
+set -eE -o pipefail
+trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
+
+hn=$(hostname -f)
+source /a/bin/bash_unpublished/source-state
+if [[ $HOSTNAME != "$MAIL_HOST" && $hn != li.b8.nz && ! $DISPLAY ]]; then
+ exit 0
+fi
+
+$s checkrestart | sed '/^Found 0 processes using old versions of upgraded files$/d'
#!/bin/bash
+# Copyright (C) 2019 Ian Kelling
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+if [ -z "$BASH_VERSION" ]; then echo "error: shell is not bash" >&2; exit 1; fi
+
+set -eE -o pipefail
+trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
+
+hn=$(hostname -f)
+source /a/bin/bash_unpublished/source-state
+if [[ $HOSTNAME == "$MAIL_HOST" || $hn == li.b8.nz ]]; then
+ exit 0
+fi
+
if [[ $(/usr/sbin/checkrestart | wc -l) != 1 ]]; then
for x in {30..1}; do
echo "pid $PID. unattended upgrade, rebooting in $((x*10)) seconds" | wall -n
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-x="$(readlink -f -- "$BASH_SOURCE")"; cd ${x%/*} # directory of this file
+x="$(readlink -f -- "${BASH_SOURCE[0]}")"; cd ${x%/*} # directory of this file
cat common.conf sway.conf > /a/bin/distro-setup/subdir_files/.config/sway/config
cat common.conf i3.conf > /a/bin/distro-setup/subdir_files/.config/i3/config
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
-x="$(readlink -f "$BASH_SOURCE")"; cd ${x%/*}
+x="$(readlink -f -- "${BASH_SOURCE[0]}")"; cd ${x%/*} # directory of this file
# scripts that would interfere with unmounting /a, put them elsewhere
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?"' ERR
-[[ $EUID == 0 ]] || exec sudo "${BASH_SOURCE}" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
if [[ $- != *i* ]]; then
exec &>/var/log/keyscript-off.log
echo "$0: starting. $(date)"
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?"' ERR
-[[ $EUID == 0 ]] || exec sudo "${BASH_SOURCE}" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
if [[ $- != *i* ]]; then
exec &>>/var/log/keyscript-on.log
echo "$0: starting. $(date)"
+++ /dev/null
-# disabled for various reasons
-# */5 * * * * /a/bin/offlineimap_cronjob
-# */1 * * * * unison ~/.mpv ssh://htpc/.mpv
-# small-backpup:
-# runs every 10 minutes, every day 4 am, every sunday at 3 am
-# stored for 3 days, 2 months, and unlimited respectively
-SHELL=/bin/bash
-0 4 * * * ian x=$(/usr/local/bin/logq /a/exe/small-backup --retry daily 2M); [[ $? != 0 ]] && echo "$x"
-0 3 * * sun ian echo weekly backup results:; /a/exe/small-backup --retry weekly
-*/10 * * * * ian /a/exe/small-backup 10minutes 3D 2>&1 | /usr/local/bin/log-once small-backup-10min
-# put things we don't want to send mail about below this:
-# MAILTO=""
# See the License for the specific language governing permissions and
# limitations under the License.
-[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
source /a/bin/errhandle/err
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
if [[ ! $SUDO_USER ]]; then
echo "$0: error: requires running as nonroot or sudo"
exit 1
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
f=/a/bin/bash_unpublished/source-state
if [[ -e $f ]]; then
systemctl restart mailcert.timer
systemctl enable mailcert.timer
-# This symlink is only here to so I can use the
-# fsf mailman ansible role and trick its cert script
-# into doing nothing.
-/a/exe/lnf -T /etc/exim4/exim.crt /etc/letsencrypt/live/$(hostname -f)/fullchain.pem
-
##### end mailcert setup #####
# comon stuff
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
shopt -s extglob nullglob
--help: print this
--end: adds to end of path, which will give it lowest priority
--ifexists: add to path only if directory exists"
- local found x y z ifexists end loop newpath
+ local found x y ifexists end loop newpath
ifexists=false
end=false
loop=true
rng-tools
sakura
schroot
+ shellcheck
sig2dot
sipcalc
sqlite3-doc
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-if [[ ! $SUDO_USER || $EUID == 0 ]]; then
+if [[ $EUID == 0 && ! $SUDO_USER ]]; then
echo "$0: error: requires running as nonroot or sudo"
exit 1
fi
source /a/bin/bash_unpublished/source-state
fi
-if [[ $HOSTNAME == $MAIL_HOST ]]; then
+if [[ $HOSTNAME == "$MAIL_HOST" ]]; then
# arbtt disabled for now
#DISPLAY=:0 arbtt-capture --sample-rate=10 &
sudo systemctl start rss2email.timer
#!/bin/bash
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
if [[ -e /b/errhandle/err ]]; then
source /b/errhandle/err
pi-nostart radicale
# use persistent uid/gid
-IFS=:; read _ _ uid _ < <(getent passwd radicale ); unset IFS
-IFS=:; read _ _ gid _ < <(getent group radicale ); unset IFS
+IFS=:; read -r _ _ uid _ < <(getent passwd radicale ); unset IFS
+IFS=:; read -r _ _ gid _ < <(getent group radicale ); unset IFS
if [[ $uid != 609 ]]; then
systemctl stop radicale ||:
usermod -u 609 radicale
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
dest=/root/.ssh
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
for n in stretch jessie; do
if [[ -e /etc/schroot/chroot.d/$n.conf ]]; then
new_host=$2
source /a/bin/bash_unpublished/source-state
-if [[ $old_host != $MAIL_HOST ]]; then
- read -p "warning: \$old_host != \$MAIL_HOST: $old_host != $MAIL_HOST, proceed? y/N "
+if [[ $old_host != "$MAIL_HOST" ]]; then
+ read -r -p "warning: \$old_host != \$MAIL_HOST: $old_host != $MAIL_HOST, proceed? y/N "
if [[ $REPLY != [yY] ]]; then
exit 1
fi
chars=()
glob=(/nocow/btrfs-stale/*)
- if [[ -e $glob ]] ; then
+ if [[ -e ${glob[0]} ]]; then
chars+=("STALE!")
fi
glob=(/m/md/bounces/new/*)
- if [[ -e $glob ]]; then
+ if [[ -e ${glob[0]} ]]; then
chars+=("BOUNCE!")
lo -1 bounce "message in /m/md/bounces/new"
fi
glob=(/m/md/alerts/new/* /m/md/alerts/cur/*)
- if [[ -e $glob ]]; then
+ if [[ -e ${glob[0]} ]]; then
chars+=("ALERT!")
fi
if [[ -e /nocow/user/mailtest-failure ]]; then
fi
source /a/bin/bash_unpublished/source-state
- if [[ $MAIL_HOST == $HOSTNAME ]]; then
+ if [[ $MAIL_HOST == "$HOSTNAME" ]]; then
if [[ $(systemctl is-active btrbk.timer) != active ]]; then
chars+=("BTRBK.TIMER!")
lo -60 btrbk.timer "btrbk.timer not enabled"
cat /a/bin/bash_unpublished/source-state >$status_file
- if [[ $chars ]]; then
+ if [[ ${chars[*]} ]]; then
echo "ps_char=\"${chars[*]} \$ps_char\"" >>$status_file
fi
}
write-status
-if [[ $@ ]]; then
+if [[ $1 ]]; then
cat $status_file
exit 0
fi
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
# Usage: run when switching from an untrusted network like public wifi
# to a trusted one.
set -eE -o pipefail
trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
-[[ $EUID == 0 ]] || exec sudo -E "$BASH_SOURCE" "$@"
+[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
# Usage: use when switching from a trusted network to an untrusted one,
# like public wifi.