#!/bin/bash
-# Copyright (C) 2019 Ian Kelling
-# SPDX-License-Identifier: AGPL-3.0-or-later
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to switch
+# its license to GPL.
+
+# Copyright 2024 Ian Kelling
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# this gets sourced. shebang is just for file mode detection
export NOT_MAIL_HOST_P=t
fi
-
-source /a/bin/log-quiet/logq-function
-
-# not used
-# if [[ -s /a/opt/alacritty/extra/completions/alacritty.bash ]]; then
-# source /a/opt/alacritty/extra/completions/alacritty.bash
-# fi
-
-
source /a/bin/ds/beet-data
sle() { # sl emacs
local f=/home/iank/.emacs.d/init.el
- sl --sl-test-cmd ". /etc/os-release ; printf %s \${VERSION//[^a-zA-Z0-9]/}; test -e $f && stat -c%Y $f" --sl-test-hook slemacs "$@"
+ sl --sl-test-cmd "sed -rn '/^VERSION=/{s/^.*=//;s/[^[:alnum:]]//gp}' /etc/os-release; test -e $f && stat -c%Y $f" --sl-test-hook slemacs "$@"
}
ccomp ssh sle
# usage mkschroot [-] distro codename packages
# - means no piping in of sources.list
+#
+# note some useful post mkschroot i've used in the past
+# tu /nocow/schroot/flidas/etc/sudoers <<EOF
+# $USER ALL=(ALL) NOPASSWD: ALL
+# Defaults env_keep += SUDOD
+# Defaults always_set_home
+# Defaults !umask
+# EOF
+# sd /nocow/schroot/flidas//etc/locale.gen <<'EOF'
+# en_US.UTF-8 UTF-8
+# EOF
+# s schroot -c flidas locale-gen
+# s schroot -c flidas update-locale LANG=en_US.UTF-8
+
mkschroot() {
local sources force repo n distro
force=false
}
-anki() {
- # crashes on adding new cards in t9
- schroot -c buster -- anki
-}
-
daycat() {
ngset
hrcat /m/md/daylert/{cur,new}/*
# usage: see above
_iki-convert() {
- local url url_prefix path input err repo_dir dir url_dir url name
+ local url url_prefix path input repo_dir dir url_dir url name
url_prefix="$1"
name="${url_prefix%%.*}"
repo_dir="/f/$name"
case $input in
http*)
path="$repo_dir/${input##http*://"$url_prefix"/}"
+ # for files like x.jpg, we dont need to convert the extension.
if [[ $path == */ ]]; then
path=${path%/}.mdwn
+ # brains adds trailing slash, but without trailing is still
+ # valid. We can't be totally sure whether to add mdwn, but we
+ # can guess based on the existence of the file. We can't be sure
+ # because it could be a file like x.jpg, that we just don't have
+ # in our local repo.
+ elif [[ ! -f $path && -e $path.mdwn ]]; then
+ path=${path}.mdwn
fi
j printf "%s\n" "$path"
;;
path=$(fp "$input")
url_dir=$(echo "$path" | sed -r "s,^(/a)?$repo_dir/,,")
url="https://$url_prefix/$url_dir"
- url="${url%.mdwn}/"
+ if [[ $url == *.mdwn ]]; then
+ url="${url%.mdwn}/"
+ fi
j echo "$url"
;;
esac
mpvrpco '{ "command": ["get_property", "percent-pos"] }' | jq .data | sed 's/\..*/%/' 2>/dev/null ||:
}
+# run if not running.
+#
+# Note: this does not work with shell scripts as they are normally
+# invoked, because the ps output has the interpreter at the start.
+# A workaround is to invoke the command in that format, or we could
+# do various other workarounds.
+#
+# background, this relies on how ps converts newlines in arguments to spaces, and
+# assumes we won't be searching for a command with spaces in its arguments
+rinr() {
+ # shellcheck disable=SC2009 # pgrep has no fixed string option, plus see above.
+ if ps h -o args -C "${1##*/}" | grep -Fxqv "$*" &>/dev/null || [[ $? == 141 ]]; then
+ "$@"
+ fi
+}
+# variation of above: run or wait if running
+rowir() {
+ local pid
+ pid=$(ps h -o 'pid,args' -C "${1##*/}" | sed -r 's/^[[:space:]]*([0-9]+)[[:space:]](.*)/\1\n\2/' | grep -B1 -Fx "$*" | head -n1 ||: )
+ if [[ $pid ]]; then
+ # https://unix.stackexchange.com/questions/427115/listen-for-exit-of-process-given-pid
+ tail --pid="$pid" -f /dev/null
+ else
+ "$@"
+ fi
+}
+
+mpvrpc-loadfile() {
+ local path nextpath cachedir finalpath nextpath count
+ cachedir=$HOME/.iank-music-cache
+ path="$1"
+ nextpath="$2"
+
+ # note: logic duplicated in beetpull
+ local remote_p=true
+ if [[ $HOSTNAME == kd ]]; then
+ remote_p=false
+ fi
+
+ if $remote_p; then
+ finalpath="$cachedir${path#/i/m}"
+ rowir rsync --partial -a --inplace --mkpath "b8.nz:$path" "$finalpath"
+ finalnextpath="$cachedir${nextpath#/i/m}"
+ count=$(pgrep -a -f "^rsync --partial -a --inplace --mkpath $cachedir" || [[ $? == 1 ]] )
+ # allow us to start 2 rsyncs in the background
+ if [[ $count == [01] ]]; then
+ rinr rsync --partial -a --inplace --mkpath "b8.nz:$nextpath" "$finalnextpath" &
+ fi
+ else
+ finalpath="$path"
+ fi
+ mpvrpc '{ "command": ["loadfile", "'"$finalpath"'"] }'
+}
+
# tag with beets.
# usage: beetag [-r] [-s] QUERY
# it lists the query, reads an input char for tagging one by one.
# q quit
# ret next
#
+# todo: enter should also unpause
beetag() {
local last_genre_i fstring tag id char new_item char_i genre tag remove doplay i j random path
- local do_rare_genres read_wait help line lsout tmp ls_line skip_lookback
+ local do_rare_genres read_wait line lsout tmp ls_line skip_lookback
local escape_char escaped_input expected_input skip_input_regex right_pad erasable_line seek_sec
local pl_state_path pl_state_dir pl_state_file tmpstr
local new_random pl_seed_path seed_num seed_file fmt first_play repeat1
fi
### end arg processing ###
- beetpull
+ # note: I used to do beetpull here, but mpv + ssfs on slowish
+ # connection leads to bad/buggy result.
do_rare_genres=false
volume=70
first_play=false
for (( i=0; i<20; i++ )); do
if [[ $(mpvrpco '{ "command": ["get_property", "idle-active"] }' 2>/dev/null | jq .data) == true ]]; then
- mpvrpc '{ "command": ["loadfile", "'"$path"'"] }' 2>/dev/null
+ mpvrpc-loadfile "$path" 2>/dev/null
break
fi
sleep .1
done
else
- mpvrpc '{ "command": ["loadfile", "'"$path"'"] }'
+ mpvrpc-loadfile "$path"
fi
erasable_line=false
fi
doplay=false
else
doplay=true
- mpvrpc '{ "command": ["loadfile", "'"$path"'"] }'
+ mpvrpc-loadfile "$path"
erasable_line=false
fi
beetag-nostatus 1
# $ dig ns1.gnu.org @b0.org.afilias-nst.org.
-# todo: make sm pull/push use systemd instead of the journal cat command
bbk() { # btrbk wrapper
local ret=0
c /
dsign iankelling.org expertpathologyreview.com zroe.org amnimal.ninja
lipush
for h in li bk; do
- m sl $h.b8.nz <<'EOF'
-source ~/.bashrc
-m dnsup
-EOF
+ m ssh $h.b8.nz dnsup
done
}
bindpushb8() {
lipush
for h in li bk; do
- m sl $h <<'EOF'
-source ~/.bashrc
-m dnsb8
-EOF
+ m ssh $h.b8.nz dnsb8
done
}
dnsb8() {
local f=/var/lib/bind/db.b8.nz
m ser stop named
- m sleep 1
- m sudo rm -fv $f.jnl $f.signed.jnl
+ # jbk is like a temp file. dunno if removing it helps
+
+ i=0
+ while pgrep '^named$' &>/dev/null; do
+ sleep .5
+ i=$(( i + 1 ))
+ if (( i > 100 )); then
+ echo "dnsb8: error: timeout waiting for named to exit"
+ return 1
+ fi
+ done
+ m sudo rm -fv $f.jnl $f.signed.jnl $f.jbk
m sudo install -m 644 -o bind -g bind /p/c/machine_specific/vps/bind-initial/db.b8.nz $f
m ser restart named
}
# set day start for use in other programs.
# expected to do be in a format like 830, or 800 or 1300.
ds() {
+ local regex
+ regex='[0-9]?[0-9]?[0-9][0-9]'
if [[ $1 ]]; then
+ if [[ ! $1 =~ $regex ]]; then
+ echo "ds: error. expected \$1 to match $regex, got \$1: $1"
+ return 1
+ fi
echo $1 >/b/data/daystart
else
cat /b/data/daystart
}
# Bitcoin holds open the wallet file. this causes problems for a
-# secondary computer running bitcoin and receiving a backup. So, as a
-# workaround, I intend to manually enable the wallet when I want to use
-# it and leave it disabled otherwise.
+# secondary computer running bitcoin and receiving a backup (as of
+# 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.
+#
+# 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
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
}
+
+
+apache-header() {
+ # First paragraph is to avoid people being confused about why a
+ # file is apache licensed.
+ cat <<'EOF'
+# I, Ian Kelling, follow the GNU license recommendations at
+# https://www.gnu.org/licenses/license-recommendations.en.html. They
+# recommend that small programs, < 300 lines, be licensed under the
+# Apache License 2.0. This file contains or is part of one or more small
+# programs. If a small program grows beyond 300 lines, I plan to change
+# to a recommended GPL license.
+
+# Copyright 2024 Ian Kelling
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+EOF
+
+}
+
+# apply apache to git tracked bash files + README, except files with A?GPL3 header.
+apache-apply-repo() {
+ for f in $(git ls-files); do
+ [[ -L $f || ! -f $f ]] && continue
+ if [[ $f != README ]]; then
+ if ! grep -n '^#!/bin/bash' $f | grep ^1: &>/dev/null; then continue; fi
+ if head -n 10 $f | grep 'it under the terms of the GNU General Public License as published by' &>/dev/null; then continue; fi
+ fi
+ apache-apply $f
+ done
+}
+
+apache-apply() {
+ for file; do
+ if head -n1 "$file"| grep -E '^#!/bin/bash\b' &>/dev/null; then
+ {
+ head -n1 "$file"
+ apache-header
+ tail -n+2 "$file"
+ } | sponge "$file"
+ else
+ {
+ apache-header
+ cat "$file"
+ } | sponge "$file"
+ fi
+ done
+}
+# strip out the apache license from a file.
+apache-strip() {
+ # shellcheck disable=SC2044 # meh
+ 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() {
if type -p chromium &>/dev/null; then
cmd=chromium
digdiff @ns{1,2}.iankelling.org "$@"
}
-tsr() { # ts run
- "$@" |& ts || return $?
-}
-
dup() {
local ran_d
ran_d=false
# test whether missing files were renamed, generally for use with fsdiff
# $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir
# echos non-renamed files
- local x y found
- unset sums
+ local x line found renamed
+ local -a sums
for x in "$2"/*; do
{ sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null
done
dejagnu() { /a/opt/dejagnu/dejagnu "$@"; }
+# do git status on published repos.
hstatus() {
- # do git status on published repos.
c /a/bin/githtml
for x in *; do
cd "$(readlink -f $x)"/..
done
}
+hsk() {
+ local x
+ c /a/bin/githtml
+ for x in *; do
+ cd "$(readlink -f $x)"/..
+ skgit
+ cd /a/bin/githtml
+ done
+}
+
## work log
#
# note: database location is specified in ~/.timetrap.yml, currently /p/.timetrap.db
cd $d$n/"$chan"
hr
for x in *; do
- echo $x; sed "s/^./${x%log}/" $x; hr;
+ # *** are parts and joins and such, and they make reading hard.
+ # I probably will want to see them sometimes, just have to
+ # remove that part.
+ echo $x; sed "s/^./${x%log}/;/\*\*\*/d" $x; hr;
done
done
}
ilog() {
- local chan
+ local chan tmpf
+ tmpf=$(mktemp)
chan="${1:-#fsfsys}"
# use * instead of -r since that does sorted order
- sl root@iankelling.org ilog-local "$chan" | less +G
+ sl root@li.b8.nz ilog-local "$chan" > $tmpf
+ less +G $tmpf
+ rm -f $tmpf
}
o() {
umask $umask_orig
}
-declare -A vpn_ips
-vpn_ips[kd]=2
-# note: 1, 4, 5 are occupied by mail wireguard
-vpn_ips[x3]=8
-vpn_ips[sy]=12
-vpn_ips[x2]=13
-vpn_ips[kw]=27
-vpn_ips[bo]=28
-vpn_ips[frodo]=34
+host-info-all() {
+ host-info-update
+
+ bindpushb8
+ # for wireguard configs
+ ssh iank@li.b8.nz conflink
+ wrt-setup
+}
+
+
+
+
+
+## for updating host info like ip, location, update /p/c/host-info and
+## host_info below. the host_info array should probably be in its own
+## file that gets sourced so that it can be more easily updated.
+
+# todo: this is so long that it becomes confusing,
+# try to split it up.
+#
+# To make some changes take effect, run host-info-all.
+host-info-update() {
+
+ local -A vpn_ips host_ips host_macs portfw_ips nonvpn_ips all_ips
+ local -a root_hosts nonroot_hosts
+
+ # the hosts with no mac
+ root_hosts=( bk je li b8.nz )
+ for h in ${root_hosts[@]}; do
+ root_hosts+=(${h}ex)
+ done
+ root_hosts+=(cmc)
+
+ while read -r ip host mac opts; do
+ if [[ $ip == *#* || ! $host ]]; then continue; fi
+
+ # opt parsing
+ vpn=false
+ root=false
+ for opt in $opts; do
+ case $opt in
+ user=root)
+ root=true
+ ;;
+ vpn)
+ vpn=true
+ ;;
+ esac
+ done
+
+ all_ips[$host]=$ip
+ if $vpn; then
+ portfw_ips[$host]=$ip
+ vpn_ips[$host]=$ip
+ else
+ nonvpn_ips[$host]=$ip
+ fi
+ if $root; then
+ # note: the reason we have b8.nz suffix here but not for non_root
+ # 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)
+ root_hosts_a[$host]=t # a for associative array
+ else
+ nonroot_hosts+=($host ${host}i)
+ fi
+ host_ips[$host]=$ip
+ if [[ $mac ]]; then
+ host_macs[$host]=$mac
+ fi
+
+ done </p/c/host-info
+
+ {
+ cat <<EOF
+Host ${nonroot_hosts[@]}
+User iank
+IdentityFile ~/.ssh/home
+
+Host ${root_hosts[@]}
+IdentityFile ~/.ssh/home
+
+EOF
+ for host in ${!vpn_ips[@]}; do
+ ipsuf=${vpn_ips[$host]}
+ cat <<EOF
+Host ${host}i ${host}i.b8.nz
+Port $((2200 + ipsuf))
+EOF
+ done
+
+ # convenience of one auth key entry
+ for host in ${!all_ips[@]}; do
+ cat <<EOF
+Host $host ${host}i $host.b8.nz ${host}i.b8.nz
+HostKeyAlias $host.b8.nz
+EOF
+ done
+ } | cedit -e /p/c/subdir_files/.ssh/config-static
+
+ {
+ # hack to please emacs parser
+ here_begin="cat <<EOF"
+ echo "$here_begin"
+ for host in ${!vpn_ips[@]}; do
+ ipsuf=${vpn_ips[$host]}
+ i_port=$(( 2200 + ipsuf ))
+ cat <<EOF
+config redirect
+option name ssh$host
+option src wan
+option src_dport $i_port
+option dest_port 22
+option dest_ip \$l.$ipsuf
+option dest lan
+config rule
+option src wan
+option target ACCEPT
+option dest_port $i_port
+EOF
+ done
+ echo "EOF"
+ } >/p/c/cmc-firewall-data
+
-vpn-ips-update() {
local host ipsuf f files
+
+ # shellcheck disable=SC2016 # shellcheck doesnt know this is sed
+ sedi '/edits below here are made automatically/,$d' /p/c/machine_specific/li/filesystem/etc/wireguard/wgmail.conf
for host in ${!vpn_ips[@]}; do
+ if [[ ${root_hosts_a[$host]} ]]; then
+ # root machines dont actually need vpn, but
+ # the classification still helps with other
+ # configurations.
+ continue
+ fi
ipsuf=${vpn_ips[$host]}
wghole $host $ipsuf
+ u /b/ds/machine_specific/li/filesystem/etc/openvpn/client-config-hole/$host <<EOF
+ifconfig-push 10.5.5.${vpn_ips[$host]} 255.255.255.0
+EOF
u /a/bin/ds/machine_specific/$host/filesystem/etc/systemd/system/openvpn-client-tr@.service <<EOF
[Unit]
Description=OpenVPN tunnel for %I
done
{
- for host in ${!vpn_ips[@]}; do
- ipsuf=${vpn_ips[$host]}
- cat <<EOF
-local-data-ptr: "10.2.0.$ipsuf $host.b8.nz"
-EOF
+ echo "cat <<EOF"
+ for host in ${!host_ips[@]}; do
+ ipsuf=${host_ips[$host]}
+ # shellcheck disable=SC2016 # intentional
+ echo 'local-data-ptr: "$l.'$ipsuf $host.b8.nz'"'
+ done
+ echo "EOF"
+ } | u /p/c/ptr-data
+
+ {
+ echo "cat <<EOF"
+ for host in ${!host_macs[@]}; do
+ ipsuf=${host_ips[$host]}
+ echo "dhcp-host=${host_macs[$host]},set:$host,\$l.$ipsuf,$host"
done
- } | u /b/ds/ptr-data
+ echo "EOF"
+ } | u /p/c/dnsmasq-data
+
+ b8_ip=$(dig +short b8.nz @iankelling.org | tail -1)
+ if [[ ! $b8_ip ]]; then
+ echo "$0: error: got empty b8.nz ip. returning 1"
+ return 1
+ fi
{
+ echo "@ A $b8_ip"
+ for host in ${!nonvpn_ips[@]}; do
+ ipsuf=${nonvpn_ips[$host]}
+ echo "$host A 10.2.0.$ipsuf"
+ done
for host in ${!vpn_ips[@]}; do
ipsuf=${vpn_ips[$host]}
cat <<EOF
${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
EOF
done
- } | cedit vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz ||:
+ } | cedit -e vpn-ips-update /p/c/machine_specific/vps/bind-initial/db.b8.nz
echo checking for stray files:
- initial_dir=$PWD
- cd /a/bin/ds/machine_specific
- ngset
- files=( */filesystem/etc/systemd/system/openvpn-client-tr@.service )
- ngreset
- cd $initial_dir
+ initial_dir="$PWD"
+ while read -r dir path; do
+ cd $dir
+ ngset
+ files=( */$path )
+ ngreset
+ cd "$initial_dir"
+ for f in "${files[@]}"; do
+ host=${f%%/*}
+ if [[ ! ${vpn_ips[$host]} ]]; then
+ e rm $dir/$f
+ fi
+ done
+ done <<'EOF'
+/a/bin/ds/machine_specific filesystem/etc/systemd/system/openvpn-client-tr@.service
+/p/c/machine_specific filesystem/etc/wireguard/wghole.conf
+EOF
+
+ files=( /b/ds/machine_specific/li/filesystem/etc/openvpn/client-config-hole/* )
for f in "${files[@]}"; do
- host=${f%%/*}
+ host=${f##*/}
if [[ ! ${vpn_ips[$host]} ]]; then
- e /a/bin/ds/machine_specific/$host/filesystem/etc/systemd/system/openvpn-client-tr@.service
+ e rm $f
+ e ssh root@li.b8.nz rm -f $f
fi
done
- cd /p/c/machine_specific
- ngset
- files=( */filesystem/etc/wireguard/wghole.conf )
- ngreset
- cd $initial_dir
- for f in "${files[@]}"; do
- host=${f%%/*}
- if [[ ! ${vpn_ips[$host]} ]]; then
- e /p/c/machine_specific/$host/filesystem/etc/wireguard/wghole.conf
- e cedit -s $host /p/c/machine_specific/li/filesystem/etc/wireguard/wgmail.conf '<<<""'
+ 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
+ echo "IdentityFile ~/.ssh/work"
+ } >$tmpf
+ cedit -e work-identity /p/c/subdir_files/.ssh/config-static <$tmpf
+ rm -f $tmpf
+
+ ### begin focus on hosts file update ###
+ #
+ # This started as its own function, but it actually
+ # needed to alter the ssh config, so combined it.
+ #
+ # background: This is finally doing dynamic ip resolution via the hosts
+ # file. I considered detecting where each host was dynamically or
+ # something, but ultimately decided to mostly avoid that, other than
+ # detecting the status of the current machine I'm on. I want to be able
+ # to move it around without having to manually type much of anything.
+ local -a host_domain_suffix hosts
+ local -A ip_to_hosts
+ local suf ip i host at_home suf_from_here
+
+ source /p/c/domain-info
+
+ at_home=false
+ if ip n | grep -q "10.2.0.1 .* b4:75:0e:fd:06:4a"; then
+ at_home=true
+ fi
+
+ for i in ${host_domain_suffix[@]}; do
+ if [[ $i == *.* ]]; then
+ suf=$i
+ continue
fi
+ hosts+=($i)
+ if [[ $i == "$HOSTNAME" ]]; then
+ unset "portfw_ips[$i]"
+ continue
+ fi
+
+ suf_from_here=$suf
+ if ! $at_home && [[ $suf == .b8.nz || $suf == [wc].b8.nz ]]; then
+ suf_from_here=i.b8.nz
+ else
+ unset "portfw_ips[$i]"
+ fi
+
+ ip=$(getent ahostsv4 "$i$suf_from_here" | awk '{ print $1 }' | head -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"
done
+
+ for ip in "${!ip_to_hosts[@]}"; do
+ echo "$ip${ip_to_hosts[$ip]}"
+ 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
+ ### end focus on hosts file update ###
+
+
+ # note: note sure if this is a great way to check.
+ # todo: think about it
+
+ if $at_home; then
+ # possible that in the future we want to create
+ # a dynamic file here, and then we can move the cat
+ # command above out of the conditional
+ rsync -a /p/c/subdir_files/.ssh/config-static ~/.ssh/config
+ else
+ for host in ${!portfw_ips[@]}; do
+ ipsuf=${portfw_ips[$host]}
+ cat <<EOF
+Host ${host}
+Port $((2200 + ipsuf))
+EOF
+ done > ~/.ssh/config-dynamic
+ cat /p/c/subdir_files/.ssh/config-static ~/.ssh/config-dynamic >~/.ssh/config
+ fi
}
# usage host ipsuf [extrahost]
two=false
case $1 in
- -2) two=true shift ;;
+ -2) two=true; shift ;;
esac
for md; do
mpvd() {
mpv --profile=d "$@";
}
+mpva() {
+ mpv --profile=a "$@";
+}
# mpv all media files in . or $1
mpvm() {
local -a extensions arg
"$@" |& pee "xclip -r -selection clipboard" cat
}
-# x copy
+# xorg copy. copy text piped into command
xc() {
xclip -r -selection clipboard
}
}
spamf() { # spamtest on FILE
- local spamcpre spamdpid
-
if (( $# != 1 )); then
e spamtest error: expected 1 arg, filename >&2
return 1
fi
-
- spamdpid=$(systemctl status spamassassin| sed -n '/^ *Main PID:/s/[^0-9]//gp')
- spamcpre="nsenter -t $spamdpid -n -m"
- s $spamcpre sudo -u Debian-exim spamassassin -t --cf='score PYZOR_CHECK 0' <"$1"
+ sdncmdroot spamassassin sudo -u Debian-exim spamassassin -t --cf='score PYZOR_CHECK 0' <"$1"
}
$s /a/exe/teeu "$@"
}
+# execute exim in its namespace. Useful args like -Mrm
enn() {
local ecmd pid
ecmd="/usr/sbin/exim4 -C /etc/exim4/my.conf"
if ip a show veth1-mail &>/dev/null; then
s $ecmd "$@"
- return
+ else
+ sdncmdroot exim4 $ecmd "$@"
fi
- pid=$(pgrep -f "/usr/sbin/exim4 -bd -q10m -C /etc/exim4/my.conf"|h1)
- m s nsenter -t $pid -n -m $ecmd "$@"
}
# get pid of systemd service
m sudo nsenter -t $pid -n -m sudo -u $USER -i bash
}
-sdnbashroot() { # systemd namespace bash
+sdnbashroot() { # systemd namespace bash as root
local unit pid
if (( $# != 1 )); then
echo $0: error wrong number of args >&2
}
-sdncmd() { # systemd namespace cmd
+# systemd namespace cmd
+# usage: UNIT CMD...
+sdncmd() {
local unit pid tmpf
- if (( $# <= 2 )); then
+ if (( $# <= 1 )); then
echo $0: error wrong number of args >&2
return 1
fi
m sudo nsenter -t $pid -n -m sudo -u $USER -i bash -c ". $tmpf & rm $tmpf"
}
+sdncmdroot() { # systemd namespace root command
+ local unit pid
+ if (( $# < 2 )); then
+ echo $0: error wrong number of args >&2
+ return 1
+ fi
+ unit=$1
+ shift
+ pid=$(servicepid $unit)
+ m sudo nsenter -t $pid -n -m "$@"
+}
+
mailnnbash() {
sdnbash mailnn
# }
eximbash() {
- local pid
- pid=$(pgrep -f "/usr/sbin/exim4 -bd -q10m -C /etc/exim4/my.conf"|h1)
- if [[ ! $pid ]]; then
- echo "eximbash: failed to find exim pid. systemctl -n 30 status exim4:"
- systemctl status exim4
- fi
- m sudo nsenter -t $pid -n -m
+ sdnbashroot exim4
}
spamnn() {
local spamdpid
m sudo nsenter -t $spamdpid -n -m sudo -u Debian-exim spamassassin "$@"
}
unboundbash() {
- m sudo nsenter -t "$(systemctl status unbound| sed -n '/^ *Main PID:/s/[^0-9]//gp')" -n -m sudo -u $USER -i bash
+ sdnbashroot unbound
}
nmtc() {
vpncmd() {
- m sudo -E env "PATH=$PATH" nsenter -t "$(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*client.conf")" -n "$@"
+ sdncmd openvpn-client-tr@client.service "$@"
}
-
vpni() {
- vpncmd sudo -u iank env "PATH=$PATH" "$@"
+ sdncmd openvpn-client-tr@client.service bash
}
vpnbash() {
- vpncmd bash
+ sdncmdroot openvpn-client-tr@client.service bash
}
um() {
local sink card
sink=$(pactl get-default-sink)
- if [[ $sink != auto_null ]]; then
- return
+ 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}')
+ m pacmd set-card-profile "$card" output:analog-stereo
fi
- # 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}')
- m pacmd set-card-profile "$card" output:analog-stereo
-
- pactl set-sink-mute @DEFAULT_SINK@ false
+ m pactl set-sink-mute @DEFAULT_SINK@ false
rm -f /tmp/ianknap
}
"$@"
}
-f=/a/f/ansible-configs/files/common/etc/fsf-workstation-bashrc.sh
-if [[ -e $f ]]; then
- # shellcheck disable=SC1090
- source $f
-fi
-
electrum() {
# https://electrum.readthedocs.io/en/latest/tor.html
# https://github.com/spesmilo/electrum-docs/issues/129
}
+# grep + find
+gef() {
+ faf | grep -E "$@" ||:
+ rgv "$@"
+}
+
# rg my main files
rgm() {
rg "$@" /p/w.org /a/t.org /a/work.org /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 -- "$*" $paths /a/t.org /p/w.org /a/work.org ||:
+ rgv $local_rgv_args -g "!bash_unpublished" -- "$*" $paths /a/work.org ||:
}
-reml() { # with limit to 5 matches per file
+reml() { # rem with limit to 5 matches per file
+ local_rgv_args="-m 5"
+ rem "$@"
+}
+
+rep() {
local paths
- paths="/p/c /b"
+ paths="/p/c"
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 -m 5 -- "$*" $paths /a/t.org /p/w.org /a/work.org ||:
+ rgv $local_rgv_args -- "$*" $paths /a/t.org /p/w.org ||:
+}
+repl() { # rem with limit to 5 matches per file
+ local local_rgv_args="-m 5"
+ rem "$@"
+}
+
+
+# re on common fsf files
+ref() {
+ local paths
+ paths="/f/gluestick /f/brains /f/s /c"
+ 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 -- "$*" $paths /a/work.org ||:
}
}
-export GOPATH=$HOME/go
-path-add $GOPATH/bin
-path-add /usr/local/go/bin
# I have the git repo and a release. either one should work.
# I have both because I was trying to solve an issue that
case $HOSTNAME in
sy|kd)
hosts=(
- kd x3.office.fsf.org syw
+ kd.b8.nz x3.office.fsf.org syw x2.b8.nz
)
;;
x3)
rm -fv /tmp/noi3bar
}
+# example:
+# <#part type="image/jpeg" filename="/home/iank/2023-12-24-ski-trip.jpg" disposition=attachment> <#/part>
+#
+attach-txt() {
+ local f
+ for f; do
+ if [[ ! -s $f ]]; then
+ e "error: empty or non-existent file $f"
+ return 1
+ fi
+ done
+ for f; do
+ echo '<#part type="image/jpeg" filename="'"$(rl "$f")"'" disposition=attachment> <#/part>'
+ done | ec
+}
+
+ctof() {
+ units "tempC($1)" tempF
+}
+
+ftoc() {
+ units "tempF($1)" tempC
+}
+
+# requires dns/firewall setup first
+local-icecast() {
+ web-conf -e ian@iankelling.org -f 8000 - apache2 live.iankelling.org <<'EOF'
+<Location "/fsf.webm">
+AuthType Basic
+AuthName "basic_auth"
+# created with
+# htpasswd -c icecast-fsf-htpasswd USERNAME
+AuthUserFile "/etc/icecast-fsf-htpasswd"
+Require valid-user
+</Location>
+<Location "/fsf-tech.webm">
+AuthType Basic
+AuthName "basic_auth"
+AuthUserFile "/etc/icecast-fsf-tech-htpasswd"
+Require valid-user
+</Location>
+EOF
+}
+
+# obs screen switching of
+obof() {
+ ls -l /tmp/no-obs-auto-scene-switch
+ touch /tmp/no-obs-auto-scene-switch
+}
+# obs screen switching on
+obon() {
+ ls -l /tmp/no-obs-auto-scene-switch
+ if [[ -e /tmp/no-obs-auto-scene-switch ]]; then
+ rm -f /tmp/no-obs-auto-scene-switch
+ fi
+}
+
+obs-gen-profiles() {
+ local p=/p/c/basic/profiles
+ sed 's/fsf-sysops/fsf-tech/g' $p/fsfsysops/basic.ini >$p/fsftech/basic.ini
+ sed 's/fsf-sysops/fsf/g' $p/fsfsysops/basic.ini >$p/fsf/basic.ini
+}
+
+# terminal clear. like clear, but put the prompt at the bottom,
+# useful for obs streaming the bottom half of a terminal window.
+tclear() {
+ for ((i=0; i<COLUMNS; i++)); do
+ echo
+ done
+}
+
+opensslcertinfo() {
+ openssl x509 -txt -in "$@"
+}
export BASEFILE_DIR=/a/bin/fai-basefiles