HISTFILE=
c() { cd "$@"; }
elif [[ $HISTFILE ]]; then
- HISTFILE=$HOME/.bh
+ # use an alternate history file when we are streaming.
+ if [[ -e $HOME/.iank-stream-on ]]; then
+ HISTFILE=/a/bin/data/stream_hist
+ else
+ HISTFILE=$HOME/.bh
+ fi
fi
+# history personal
+hip() {
+ history -c
+ HISTFILE=$HOME/.bh
+ history -r
+}
+
+# history for streaming
+his() {
+ history -c
+ HISTFILE=/a/bin/data/stream_hist
+ history -r
+}
+
+
source /a/bin/distro-setup/path-add-function
path-add /a/exe
# add this with absolute paths as needed for better security
# s sshfs bu@$host:/bu/home/md /bu/mnt -o reconnect,ServerAliveInterval=20,ServerAliveCountMax=30 -o allow_other
edelayoff() {
- echo all >/etc/exim4/no-delay-eximids
+ echo all >/var/spool/exim4/gw/.no-delay-eximids
+ if [[ $EUID == 0 ]]; then
+ chown iank:iank /var/spool/exim4/gw/.no-delay-eximids
+ fi
}
edelayon() {
- echo >/etc/exim4/no-delay-eximids
+ echo >/var/spool/exim4/gw/.no-delay-eximids
+ if [[ $EUID == 0 ]]; then
+ chown iank:iank /var/spool/exim4/gw/.no-delay-eximids
+ fi
}
eqgo() {
local -a array tmpstr delayon
delayon=true
- if grep -qFx all /etc/exim4/no-delay-eximids; then
+ if grep -qFx all /var/spool/exim4/gw/.no-delay-eximids; then
delayon=false
fi
if $delayon; then
- echo all >/etc/exim4/no-delay-eximids
+ echo all >/var/spool/exim4/gw/.no-delay-eximids
fi
tmpstr=$(exiqgrep -i -r.\*)
mapfile -t array <<<"$tmpstr"
enn -M "${array[@]}"
if $delayon; then
- echo >/etc/exim4/no-delay-eximids
+ echo >/var/spool/exim4/gw/.no-delay-eximids
fi
}
eqgo1() {
local eid
eid="$(exipick -i -r.\*|h1)"
- sed -n "/^all$/p;\$a $eid" /etc/exim4/no-delay-eximids
+ sed -n "/^all$/p;\$a $eid" /var/spool/exim4/gw/.no-delay-eximids
enn -M "$eid"
}
+# exim -M (in namespace and without delay)
ennm() {
local eid
for eid; do
- printf "%s\n" "$eid" >>/etc/exim4/no-delay-eximids
+ printf "%s\n" "$eid" >>/var/spool/exim4/gw/.no-delay-eximids
done
enn -M "$@"
}
ap() {
# pushd in case current directory has an ansible.cfg file
pushd /a/xans >/dev/null
- ansible-playbook -v -l ${1:- $(hostname -f)} site.yml
+ ansible-playbook -v -i ${1:- $(hostname -f)}, site.yml
popd >/dev/null
}
aw() {
else
pl_state_file=sorted
fi
- pl_state_dir=/i/info/pl-state
+ pl_state_dir=/b/data/pl-state
if [[ $playlist ]]; then
pl_state_dir=$pl_state_dir/$playlist
else
if [[ $cmd != /* ]]; then
cmd=$(type -P "$cmd")
fi
+ #note date format for since is date '+%F %T'
# -q = quiet
- journalctl -qn2 -f -u "$cmd_name" &
- # Trial and error of time needed to avoid missing initial lines.
- # .5 was not reliable. 1 was not reliable. 2 was not reliable
- sleep 4
+ journalctl --since=now -qn2 -f -u "$cmd_name" &
jr_pid=$!
# note, we could have a version that does system --user, but if for example
# it does sudo ssh, that will leave a process around that we can't kill
local p a
# excluding emacs for now
#p=(/a/opt/{emacs-debian11{,-nox},mu,emacs} /a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts})
- p=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts} /c/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter /a/opt/fpaste)
+ p=(
+ /a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts}
+ /c/roles/prom_export/files/simple/usr/local/bin/fsf-install-node-exporter
+ /a/opt/fpaste
+ /p/c/user-specific/www-data/icecast-fsf{,-tech}-htpasswd
+ /p/c/icecast.xml
+ )
a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes"
ret=0
for h in li je bk; do
dsign iankelling.org expertpathologyreview.com zroe.org amnimal.ninja
lipush
for h in li bk; do
- m ssh $h.b8.nz dnsup
+ m ssh iank@$h.b8.nz dnsup
done
}
bindpushb8() {
# 2023). However, in 2024-02, I ran a backup where a receiving machine
# had the wallet enabled and there was no error, so I don't know if this
# is still an issue or likely it is an inconsistent behavior.
+# Note: a pruned node won't allow for a wallet to be added, super lame
+# so i'm just not running a bitcoin node for now.
+# Error: Prune: last wallet synchronisation goes beyond pruned data. You
+# need to -reindex (download the whole blockchain again in case of
+# pruned node)
#
-# As a workaround, this function is for enabling the wallet when I want
-# to use it and leave it disabled otherwise.
-walleton() {
- local active
- active=false
- no_on=true
- if [[ ! $(readlink -f /var/lib/bitcoind/wallets) == /q/wallets ]]; then
- if systemctl --quiet is-active bitcoind; then
- if [[ -e /tmp/no-bitcoinon ]]; then
- no_on=true
- else
- if [[ $EUID == 0 ]]; then
- m install -T -o iank -g iank /dev/null /tmp/no-bitcoinon
- else
- m touch /tmp/no-bitcoinon
- fi
- fi
- active=true
- m ser stop bitcoind
- fi
- m s ln -s /q/wallets /var/lib/bitcoind
- sudo chown -h bitcoin:bitcoin /var/lib/bitcoind/wallets
- if $active; then
- m ser start bitcoind
- if ! $no_on; then
- m rm /tmp/no-bitcoinon
- fi
- fi
- fi
-}
-walletoff() {
- local active
- active=false
- no_on=true
- if [[ $(readlink -f /var/lib/bitcoind/wallets) == /q/wallets ]]; then
- if systemctl --quiet is-active bitcoind; then
- if [[ -e /tmp/no-bitcoinon ]]; then
- no_on=true
- else
- if [[ $EUID == 0 ]]; then
- m install -T -o iank -g iank /dev/null /tmp/no-bitcoinon
- else
- m touch /tmp/no-bitcoinon
- fi
- fi
- active=true
- m ser stop bitcoind
- else
- echo note: bitcoind not active
- fi
- m rm /var/lib/bitcoind/wallets
- if $active; then
- # note, starting bitcoin always fails, but it actually
- # succeeds. But this is strangely not consistent.
- m ser start bitcoind
- if ! $no_on; then
- m rm /tmp/no-bitcoinon
- fi
- fi
- fi
-}
#### end bitcoin related things
apache-apply() {
for file; do
- if head -n1 "$file"| grep -E '^#!/bin/bash\b' &>/dev/null; then
+ if [[ ! -e $file ]]; then
+ echo '#!/bin/bash' >$file
+ chmod +x $file
+ fi
+ if head -n1 "$file"| grep -E '^#!/' &>/dev/null; then
{
head -n1 "$file"
apache-header
for f in $(find . -type f -maxdepth 1); do if head -n1 "$f"| grep -E '^#!/bin/bash\b' &>/dev/null; then { head -n 20 $f | tac | sed '/^# limitations under the License.$/,/^# Copyright.*Ian Kelling$/d' | tac; tail -n+21 $f; } |sponge $f; fi ; done
}
-chrome() {
+chro() {
if type -p chromium &>/dev/null; then
cmd=chromium
else
cd /
- cmd="schroot -c bullseye chromium"
+ cmd="schroot -c bookworm chromium"
CHROMIUM_FLAGS='--enable-remote-extensions' $cmd & r
fi
}
kdecd() { /usr/lib/x86_64-linux-gnu/libexec/kdeconnectd; }
-bat() {
+batp() {
cat /sys/class/power_supply/BAT0/capacity
}
# hosts is that it is for the User part, the IdentityFile part is
# redundant to *.b8.nz. Also note ${host}i, we only setup those for vpn hosts, but there is no harm in overspecifying here.
root_hosts+=($host ${host}i $host.b8.nz ${host}i.b8.nz)
+ # shellcheck disable=SC2004 # false positive
root_hosts_a[$host]=t # a for associative array
else
nonroot_hosts+=($host ${host}i)
b8_ip=$(dig +short b8.nz @iankelling.org | tail -1)
+ # if our dynamic ip updates broke, set manually, eg:
+ #b8_ip=72.74.193.xxx
if [[ ! $b8_ip ]]; then
echo "$0: error: got empty b8.nz ip. returning 1"
return 1
fi
{
- echo "@ A $b8_ip"
+ cat <<EOF
+@ A $b8_ip
+i A $b8_ip
+EOF
for host in ${!nonvpn_ips[@]}; do
ipsuf=${nonvpn_ips[$host]}
echo "$host A 10.2.0.$ipsuf"
${host}wg A 10.8.0.$ipsuf
${host}vp A 10.5.5.$ipsuf
${host}tr A 10.174.$ipsuf.2
-${host}i A $b8_ip
+${host}i CNAME i.b8.nz.
EOF
done
} | cedit -e vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz
tmpf=$(mktemp)
{
printf "%s" "Host * "
- sed -n '/^Host /h;/^IdentityFile .*\/home/{g;s/^Host//;s/ / !/gp}' /p/c/subdir_files/.ssh/config-static | tr '\n' ' '
- echo
+ sed -n '/^Host /h;/^IdentityFile .*\/home/{g;s/^Host//;s/ / !/gp}' /p/c/subdir_files/.ssh/config-static | tr '\n' ' ' \
+ | sed -r 's/ *$/\n/'
echo "IdentityFile ~/.ssh/work"
} >$tmpf
cedit -e work-identity /p/c/subdir_files/.ssh/config-static <$tmpf
unset "portfw_ips[$i]"
fi
- ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -n1) ||:
+ # note this might be outdated until we do a dns push
+ ip=$(dig +short "$i$suf_from_here" @iankelling.org | tail -n1) ||:
if [[ ! $ip ]]; then
if [[ $suf == .office.fsf.org ]]; then
suf_from_here=wg.b8.nz
ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -n1) ||:
fi
- if [[ ! $ip ]]; then
- echo error: failed to get ip of "$i$suf_from_here"
- return 1
- fi
fi
- ip_to_hosts[$ip]+=" $i"
+ if [[ $ip ]]; then
+ ip_to_hosts[$ip]+=" $i"
+ else
+ echo error: failed to get ip of "$i$suf_from_here"
+ fi
done
for ip in "${!ip_to_hosts[@]}"; do
done | s cedit -e hosts-file-up /etc/hosts
for host in ${hosts[@]}; do
echo $host
- done | cedit -e /a/bin/ds/subdir_files/.dsh/group/btrbk
+ done >/p/c/subdir_files/.dsh/group/btrbk
### end focus on hosts file update ###
)
}
+# sudo maybe
+#
+# passes on any initial -* args to sudo.
+sudm() {
+ local arg
+ local -a sudo_opts
+ for arg; do
+ if [[ $arg == -* ]]; then
+ sudo_opts+=("$arg")
+ shift
+ else
+ break
+ fi
+ done
+ if [[ $EUID == 0 ]]; then
+ "$@"
+ else
+ sudo "${sudo_opts[@]}" "$@"
+ fi
+}
-mns() { # mount namespace
+mns-setup() {
+ local ns
ns=$1
- shift
- s mkdir -p /root/mount_namespaces
- if ! sudo mountpoint /root/mount_namespaces >/dev/null; then
- m sudo mount --bind /root/mount_namespaces /root/mount_namespaces
+ sudm mkdir -p /root/mount_namespaces
+ if ! sudm mountpoint /root/mount_namespaces >/dev/null; then
+ m sudm mount --bind /root/mount_namespaces /root/mount_namespaces
fi
- m sudo mount --make-private /root/mount_namespaces
- if [[ ! -e /root/mount_namespaces/$ns ]]; then
- m sudo touch /root/mount_namespaces/$ns
+ m sudm mount --make-private /root/mount_namespaces
+ if ! sudm test -e /root/mount_namespaces/$ns; then
+ m sudm touch /root/mount_namespaces/$ns
fi
- if ! sudo mountpoint /root/mount_namespaces/$ns >/dev/null; then
- m sudo unshare --propagation slave --mount=/root/mount_namespaces/$ns /bin/true
+ if ! sudm mountpoint /root/mount_namespaces/$ns >/dev/null; then
+ m sudm unshare --propagation slave --mount=/root/mount_namespaces/$ns /bin/true
fi
- m sudo -E /usr/bin/nsenter --mount=/root/mount_namespaces/$ns "$@"
+
+}
+
+mns() { # mount namespace
+ local ns
+ ns=$1
+ shift
+ mns-setup $ns
+ m sudm -E /usr/bin/nsenter --mount=/root/mount_namespaces/$ns "$@"
}
mnsd() { # mount namespace + systemd namespace
+ local ns unit
ns=$1
unit=$2
shift 2
- s mkdir -p /root/mount_namespaces
- if ! sudo mountpoint /root/mount_namespaces >/dev/null; then
- m sudo mount --bind /root/mount_namespaces /root/mount_namespaces
- fi
- m sudo mount --make-private /root/mount_namespaces
- if [[ ! -e /root/mount_namespaces/$ns ]]; then
- m sudo touch /root/mount_namespaces/$ns
- fi
- if ! sudo mountpoint /root/mount_namespaces/$ns >/dev/null; then
- m sudo unshare --propagation slave --mount=/root/mount_namespaces/$ns /bin/true
- fi
+ mns-setup $ns
pid=$(servicepid $unit)
tmpf=$(mktemp --tmpdir $unit.XXXXXXXXXX)
pushd /home/iank/.local/share/profanity/chatlogs/iank_at_fsf.org/rooms/office_at_conference.fsf.org
logs=(*)
logcount=${#logs[@]}
- if (( logcount > 15 )); then
- i=$(( logcount - 15 ))
+ if (( logcount > 16 )); then
+ i=$(( logcount - 16 ))
else
i=0
fi
chmod +x $out
}
-smeld() { # ssh meld usage host1 host2 file
+# ssh meld. usage: host1 host2 file
+smeld() {
meld <(ssh $1 cat $3) <(ssh $2 cat $3)
}
+# remote file meld
+# usage: host file1 file2
+rmeld() {
+ local tmpdir
+ tmpdir=$(mktemp -d)
+ scp "$1:$2" "$1:$3" $tmpdir
+ meld "$tmpdir/${2##*/}" "$tmpdir/${3##*/}"
+}
+
+
spd() {
PATH=/usr/local/spdhackfix:$PATH command spd "$@"
}
}
eless2() {
- less /var/log/exim4/mymain
+ less /var/log/exim4/nondmain
}
enn() {
local ecmd pid
- ecmd="/usr/sbin/exim4 -C /etc/exim4/my.conf"
+ ecmd="/usr/sbin/exim4 -C /etc/exim4/nn-mainlog.conf"
if ip a show veth1-mail &>/dev/null; then
s $ecmd "$@"
else
}
+# systemd network namespace (not mount) cmd
+# usage: UNIT CMD...
+sdnncmd() {
+ local unit pid tmpf
+ if (( $# <= 1 )); then
+ echo $0: error wrong number of args >&2
+ return 1
+ fi
+ unit=$1
+ shift
+ pid=$(servicepid $unit)
+ tmpf=$(mktemp --tmpdir $unit.XXXXXXXXXX)
+ export -p >$tmpf
+ printf "%s " "${@@Q}" >>$tmpf
+ echo >>$tmpf
+ m sudo nsenter -t $pid -n sudo -u $USER -i bash -c ". $tmpf & rm $tmpf"
+}
+
+
mailnnbash() {
sdnbash mailnn
}
s nmtui-connect "$@"
}
+# check exim and others network namespace
mailnncheck() {
- local unit pid ns mailnn
+ local unit pid ns mailnn spamd_ser
+
+ spamd_ser=spamd
+ if systemctl cat spamassassin &>/dev/null; then
+ spamd_ser=spamassassin
+ fi
+
# mailvpn would belong on the list if using openvpn
- for unit in mailnn unbound dovecot spamassassin exim4 radicale; do
+ for unit in mailnn unbound dovecot $spamd_ser exim4 radicale; do
pid=$(servicepid $unit)
echo debug: unit=$unit pid=$pid
if [[ ! $pid ]]; then
fi
[[ $1 ]] || { echo need arg; return 1; }
- journalctl --unit=$vpn_service@$1 -f -n0 &
- # sometimes the journal doesnt open until after the vpn output
- # has happened. hoping this fixes that.
- sleep 1
+ journalctl --since=now --unit=$vpn_service@$1 -f -n0 &
sudo systemctl start $vpn_service@$1
# sometimes the ask-password agent does not work and needs a delay.
sleep .5
fi
}
-# unmute
+# unmute desktop output
um() {
- local sink card
+ local sink card sedcmd
sink=$(pactl get-default-sink)
if [[ $sink == auto_null ]]; then
# guessing there is just one with an off profile. otherwise we will
# need some other solution, like storing the card identifier that we
- # muted with nap.
- card=$(pacmd list-cards | sed -n '/^[[:space:]]*index:/{s/^[[:space:]]*index://;h};/^[[:space:]]*active profile: <off>$/{g;p;q}')
+ # muted with nap. Or, we could so some hakery with
+ # pactl -f json.
+ sedcmd='/^[[:space:]]*index:/{s/^[[:space:]]*index://;h};/^[[:space:]]*active profile: <off>$/{g;p;q}'
+ card=$(pacmd list-cards | sed -n "$sedcmd")
m pacmd set-card-profile "$card" output:analog-stereo
fi
}
electrum() {
+ # Running the appimage said fuse was not available, but try
+ # running the appimage with --appimage-extract, which worked.
+ # It seems there is no need to backup the wallet, it can be restored
+ # via the seed onto any computer that needs it.
+ /a/opt/electrum/squashfs-root/AppRun "$@"
+
+
+ # This was an old way I ran electrum over tor, and seems like I
+ # imported a bitcoin core wallet.
+ #
# https://electrum.readthedocs.io/en/latest/tor.html
# https://github.com/spesmilo/electrum-docs/issues/129
- s rsync -ptog --chown bitcoin:bitcoin ~/.Xauthority /var/lib/bitcoind/.Xauthority
- sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/electrum-4.2.1-x86_64.AppImage -p socks5:localhost:9050
+ # s rsync -ptog --chown bitcoin:bitcoin ~/.Xauthority /var/lib/bitcoind/.Xauthority
+ # sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/electrum-4.2.1-x86_64.AppImage -p socks5:localhost:9050
+
}
+
+
monero() {
sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/monero-gui-v0.17.3.2/monero-wallet-gui
}
rg "$@" /p/w.org /a/t.org /a/work.org /b
}
-# re all my files more expansively
+# re all my files more expansively.
+# usage [-OPT...] regex space combined
rem() {
local paths
+ local -a opts
+ for arg; do
+ if [[ $arg == -* ]]; then
+ opts+=("$1")
+ shift
+ else
+ break
+ fi
+ done
paths="/p/c /b/"
find $paths -not \( -name .svn -prune -o -name .git -prune \
-o -name .hg -prune -o -name .editor-backups -prune \
-o -name .undo-tree-history -prune \) 2>/dev/null | grep -iP --color=auto -- "$*" ||:
- rgv $local_rgv_args -g "!bash_unpublished" -- "$*" $paths /a/work.org ||:
+ rgv $local_rgv_args -g "!bash_unpublished" "${opts[@]}" -- "$*" $paths /a/work.org ||:
}
reml() { # rem with limit to 5 matches per file
local_rgv_args="-m 5"
# --no-messages because of annoying errors on broken symlinks
# -z = search .gz etc files
# -. = search dotfiles
- rg() { command rg -. -z --no-messages -L -i -M 900 --no-ignore-parent --no-ignore-vcs -g '!.git' -g '!auto-save-list' -g '!.savehist' "$@" || return $?; }
+ # -n --no-heading: show files and line numbers together allowing for clicking
+ rg() {
+ local path_arg
+ if [[ ${#@} == 1 ]]; then
+ path_arg=.
+ fi
+
+ command rg -. -z --no-messages -Lin --no-heading -M 900 --no-ignore-parent --no-ignore-vcs -g '!.git' -g '!auto-save-list' -g '!.savehist' "$@" $path_arg || return $?
+ }
#fails if not exist. ignore
complete -r rg 2>/dev/null ||:
else
# rg with respecting vcs ignore files
rgv() {
- ret=0
+ local path_arg ret=0
+ if [[ ${#@} == 1 ]]; then
+ path_arg=.
+ fi
# settings that are turned off for pipes, keep them on.
# Found by searching for "terminal" in --help
# --heading
# -z = search zipped files
# -i = case insensitive
# -M = max columns
+ # -n --no-heading: show files and line numbers together allowing for clicking
# --no-messages because of annoying errors on broken symlinks
# --no-ignore-parent because i have /a/.git which ignores almost everything under it.
- command rg -n --heading -. -z --no-messages -i -M 900 --no-ignore-parent -g '!.git' -g '!auto-save-list' -g '!.savehist' "$@" || ret=$?
+ command rg -n --no-heading -. -z --no-messages -i -M 900 --no-ignore-parent -g '!.git' -g '!auto-save-list' -g '!.savehist' "$@" $path_arg || ret=$?
return $ret
}
units "tempF($1)" tempC
}
-# requires dns/firewall setup first
-local-icecast() {
+# local icecast
+localic() {
+ local mod=false
+ cedit live /p/c/machine_specific/vps/filesystem/var/lib/bind/db.iankelling.org <<'EOF' || mod=true
+live CNAME b8.nz.
+EOF
+ if $mod; then
+ ip=$(ip r show default | sed -r 's/.*src ([^ ]*).*/\1/' | head -n1)
+ if [[ ! $ip ]] && timeout 1 ping -c 1 $ip; then
+ echo "error: failed to get ip: $ip" >&2
+ exit 1
+ fi
+ cat >/p/c/cmc-firewall-data-http <<EOF
+http_ip=$ip
+EOF
+ bindpush
+ wrt-setup
+ fi
web-conf -e ian@iankelling.org -f 8000 - apache2 live.iankelling.org <<'EOF'
<Location "/fsf.webm">
AuthType Basic
Require valid-user
</Location>
EOF
+ s cat /etc/letsencrypt/live/live.iankelling.org/{fullchain,privkey}.pem | s dd of=/etc/icecast2/fullchainpluskey.pem
+ ser start icecast2
+}
+# li icecast
+liic() {
+ cedit live /p/c/machine_specific/vps/filesystem/var/lib/bind/db.iankelling.org <<'EOF' || bindpush
+live A 72.14.176.105
+ AAAA 2600:3c00::f03c:91ff:fe6d:baf8
+EOF
+}
+# icecast rm -r
+icrmr() {
+ find /var/icecast -type f -delete
+ ssh li.b8.nz find /var/icecast -type f -delete
}
+
# obs screen switching of
obof() {
ls -l /tmp/no-obs-auto-scene-switch
openssl x509 -txt -in "$@"
}
+# dsh on btrbk hosts
+dsb() {
+ :
+}
+
+# dsh a file and run it
+dsa() {
+ local ret file
+ if ! parallel -j 10 scp x {}:/tmp <~/.dsh/group/btrbk; then
+ echo parallel scp failed. dsa returning $ret
+ fi
+ dsh -g btrbk
+}
+
+# temporary
+zmqsend() {
+ /nocow/t/ffmpeg-release/ffmpeg-7.0.1/tools/zmqsend "$@"
+}
+
+ffg() { /nocow/t/ffmpeg-release/ffmpeg-7.0.1/tools/graph2dot -o /tmp/g.tmp && dot -Tpng /tmp/g.tmp -o /tmp/g.png && feh /tmp/g.png; }
+
+firefox-hide-tabs() {
+
+ # without this, make tabs smaller by setting browser.uidensity 1 in about:config
+
+ profiledir=$1
+ [[ $1 ]] || return 1
+ # Related: the sidebery extension is useful.
+
+ # This is from
+ # https://raw.githubusercontent.com/MrOtherGuy/firefox-csshacks/master/chrome/hide_tabs_toolbar.css
+
+ ainsl $profiledir/chrome/userChrome.css '#TabsToolbar{ visibility: collapse !important }'
+
+}
+
+# kill lease on cmc
+klease() {
+ local tmpdir ret out
+ ret=0
+ out=$(ssh cmc dnsmasq-end-lease "$1" 2>&1) || ret=1
+ printf "%s\n" "$out"
+ if [[ $out == *"try diffing"* ]]; then
+ tmpdir=$(mktemp -d)
+ m scp cmc:/tmp/dhcp.leases cmc:/tmp/dhcp.leases.iank $tmpdir
+ m diff $tmpdir/dhcp.leases $tmpdir/dhcp.leases.iank ||:
+ rm -rf $tmpdir
+ fi
+ return $ret
+}
+
+# ffs and switch the bash history on this terminal.
+# disabled because I don't really need this and
+# the history switching is annoying for debugging.
+#
+# ffs() {
+# local last
+# last="${*: -1}"
+# if [[ $last && $last != -* && $last != sysops ]]; then
+# his
+# fi
+# command ffs "$@"
+# }
+
+i3gen() {
+ /b/ds/i3-sway/gen
+}
+
+
+# insensitive find plus edit
+ife() {
+ local tmps found_count i char file
+ local -a found_files
+ local -A button_file
+ tmps=$(ifn "$@")
+ mapfile -t found_files <<<"$tmps"
+ found_count=${#found_files[@]}
+ if (( ${#found_files[@]} == 1 )); then
+ m g ${found_files[0]}
+ else
+ i=0
+ for button in {a..z}; do
+ button_file[$button]="${found_files[$i]}"
+ echo $button: ${found_files[$i]}
+ i=$(( i + 1 ))
+ if (( i >= found_count )); then
+ break
+ fi
+ done
+ read -rsN1 -t 5 char ||:
+ file="${button_file[$char]}"
+
+ if [[ $file ]]; then
+ g "$file"
+ else
+ echo "no selection"
+ fi
+ fi
+}
+
+
export BASEFILE_DIR=/a/bin/fai-basefiles
#export ANDROID_HOME=/a/opt/android-home