lots of updates, some t11 stuff
[distro-setup] / brc2
1 #!/bin/bash
2 # Copyright (C) 2019 Ian Kelling
3 # SPDX-License-Identifier: AGPL-3.0-or-later
4 # this gets sourced. shebang is just for file mode detection
5
6
7 # * settings
8
9 if [[ $HISTFILE ]]; then
10 HISTFILE=$HOME/.bh
11 fi
12
13 source /a/bin/distro-setup/path-add-function
14 path-add /a/exe
15 # add this with absolute paths as needed for better security
16 #path-add --end /path/to/node_modules/.bin
17 ## for yarn, etc
18 #path-add --end /usr/lib/node_modules/corepack/shims/
19
20 # pip3 --user things go here:
21 path-add --end ~/.local/bin
22 path-add --ifexists --end /a/work/libremanage
23 path-add --ifexists --end /a/opt/adt-bundle*/tools /a/opt/adt-bundle*/platform-tools
24 path-add --ifexists --end /a/opt/scancode-toolkit-3.10.
25
26 case $HOSTNAME in
27 sy|bo)
28 # https://askubuntu.com/questions/1254544/vlc-crashes-when-opening-any-file-ubuntu-20-04
29 if grep -qE '^VERSION_CODENAME="(nabia|focal)"' /etc/os-release &>/dev/null; then
30 export MESA_LOADER_DRIVER_OVERRIDE=i965
31 fi
32 ;;
33 esac
34
35
36 export WCDHOME=/a
37
38
39 case $EUID in
40 0)
41 SL_SSH_ARGS="-F $HOME/.ssh/confighome"
42 ;;
43 esac
44
45
46 # * include files
47
48 # generated instead of dynamic for the benefit of shellcheck
49 #for x in /a/bin/distro-functions/src/* /a/bin/!(githtml)/*-function?(s); do echo source $x ; done
50 source /a/bin/distro-functions/src/identify-distros
51 source /a/bin/log-quiet/logq-function
52 # for x in /a/bin/bash_unpublished/source-!(.#*); do echo source $x; done
53 source /a/bin/bash_unpublished/source-semi-priv
54 source /a/bin/bash_unpublished/source-state
55
56 source /a/bin/log-quiet/logq-function
57 if [[ -s /a/opt/alacritty/extra/completions/alacritty.bash ]]; then
58 source /a/opt/alacritty/extra/completions/alacritty.bash
59 fi
60
61
62 # * functions
63
64 multimic() {
65 local i
66 local -a sources
67
68 m pactl unload-module module-loopback
69 m pactl unload-module module-null-sink
70 m pactl unload-module module-remap-source
71
72 sources=($(pacmd list-sources | sed -rn 's/.*name: <([^>]+).*/\1/p'))
73
74 if (( ! $# )); then
75 i=0
76 for s in ${sources[@]}; do
77 e $i $s
78 i=$(( i+1 ))
79 done
80 read -r l
81 set -- $l
82 fi
83 m pactl load-module module-null-sink sink_name=ianinput sink_properties=device.description=ianinputs
84 for i; do
85 m pactl load-module module-loopback source=${sources[i]} sink_dont_move=true sink=ianinput
86 done
87 pactl load-module module-remap-source source_name=iancombine master=ianinput.monitor source_properties=device.description=iancombine
88 }
89
90 hstest() {
91 install-my-scripts
92 d=$(mktemp -d)
93 sed '/^ *IdentityFile/d' ~/.ssh/config >$d/config
94 s command ssh -F $d/config -i /q/root/h "$@"
95 }
96
97 hrtest() {
98 install-my-scripts
99 d=$(mktemp -d)
100 sed '/^ *IdentityFile/d' ~/.ssh/config >$d/config
101 s rsync -e "ssh -F $d/config -i /q/root/h" "$@"
102 }
103
104
105 slemacs() {
106 local arg rtime v
107 arg="$1"
108 remote="$2"
109 if [[ $arg == [89]0Etiona* ]]; then
110 v=${arg::1}
111 rtime=${arg#*Etiona} # remote time
112 if [[ ! $rtime ]]; then
113 rtime=0
114 fi
115 dir=/a/opt/emacs-trisquel${v}-nox/.iank
116 ltime=$(stat -c%Y $dir/e/e/.emacs.d/init.el)
117 if (( ltime > rtime )); then
118 m rsync -rptL --delete --filter=". /b/ds/sl/rsync-filter" $dir "$remote":/home/iank
119 fi
120 fi
121 }
122
123 sle() { # sl emacs
124 local f=/home/iank/.emacs.d/init.el
125 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 "$@"
126 }
127 ccomp ssh sle
128
129 # Run this manually after .emacs.d changes. Otherwise, to check if
130 # files changed with find takes 90ms. sl normally only adds 25ms. We
131 # could cut it down to 10ms if we put things on a btrfs filesystem and
132 # looked for changes there, or used some inotify thing, but that seems
133 # like too much work.
134 egh() { # emacs gnuhope
135 RSYNC_RSH=ssh m rsync -rptL --delete --filter=". /b/ds/sl/rsync-filter" /a/opt/emacs-trisquel9-nox/.iank lists2d.fsf.org:.ianktrisquel_9
136 RSYNC_RSH=ssh m rsync -rptL --delete --filter=". /b/ds/sl/rsync-filter" /a/opt/emacs-trisquel8-nox/.iank lists2d.fsf.org:/home/iank
137 }
138 ekw() {
139 local shell="bash -s"
140 if [[ $HOSTNAME != kw ]]; then
141 shell="ssh kw.office.fsf.org"
142 bbk -m /a -t kw
143 fi
144 $shell <<'EOF'
145 sudo mkdir /root/.ianktrisquel_9
146 sudo rsync -rptL --delete --filter=". /b/ds/sl/rsync-filter" /a/opt/emacs-trisquel9-nox/.iank /root/.ianktrisquel_9
147 rsync -rptL --delete --filter=". /b/ds/sl/rsync-filter" /a/opt/emacs-trisquel8-nox/.iank /home/iank
148 EOF
149 }
150
151 rm-docker-iptables() {
152 s iptables -S | gr docker | gr -- -A | sed 's/-A/-D/'| while read -r l; do sudo iptables $l; done
153 s iptables -S -t nat | gr docker | gr -- -A | sed 's/-A/-D/'| while read -r l; do sudo iptables -t nat $l; done
154 s iptables -S | gr docker | gr -- -N | sed 's/-N/-X/'| while read -r l; do sudo iptables $l; done
155 s iptables -S -t nat | gr docker | gr -- -N | sed 's/-N/-X/'| while read -r l; do sudo iptables -t nat $l; done
156 }
157
158 # usage mkschroot [-] distro codename packages
159 # - means no piping in of sources.list
160 mkschroot() {
161 local force=false
162 while [[ $1 == -* ]]; do
163 case $1 in
164 -f) force=true; shift ;;
165 -s)
166 sources="$2"
167 if [[ ! -s $sources ]]; then
168 echo mkschroot: error: sources file $sources does not exist or is empty
169 return 1
170 fi
171 shift 2
172 ;;
173 esac
174 done
175 distro=$1
176 shift
177 case $distro in
178 trisquel)
179 repo=http://mirror.fsf.org/trisquel/
180 ;;
181 ubuntu)
182 repo=http://archive.ubuntu.com/ubuntu/
183 ;;
184 debian)
185 repo=http://deb.debian.org/debian/
186 ;;
187 esac
188 n=$1
189
190 shift
191 if ! $force && schroot -l | grep -xFq chroot:$n; then
192 echo "$0: $n schroot already installed, skipping"
193 return 0
194 fi
195 apps=($@)
196 d=/nocow/schroot/$n
197 sd /etc/schroot/chroot.d/$n.conf <<EOF
198 [$n]
199 description=$n
200 type=directory
201 directory=$d
202 profile=desktop
203 preserve-environment=true
204 users=$USER,user2
205 EOF
206 cd
207 if [[ ! -e $d/bin ]]; then
208 sudo mkdir -p $d
209 # resolvconf otherwise schroot fails with
210 # cp: not writing through dangling symlink '/var/run/schroot/mount/flidas-7a2362e0-81b3-4848-92c1-610203ef5976/etc/resolv.conf'
211 sudo debootstrap --exclude=resolvconf $n $d $repo
212 fi
213 if [[ $sources ]]; then
214 sudo install -m 644 $sources $d/etc/apt/sources.list
215 fi
216 sudo chroot $d apt-get update
217 sudo DEBIAN_FRONTEND=noninteractive chroot $d apt-get -y dist-upgrade --purge --auto-remove
218 sudo cp -P {,$d}/etc/localtime
219 if (( ${#apps[@]} )); then
220 sudo DEBIAN_FRONTEND=noninteractive schroot -c $n -- apt-get install --allow-unauthenticated -y ${apps[@]}
221 fi
222 }
223
224
225 # note: this is incomplete and untested.
226 # https://wiki.archlinux.org/index.php/Install_Arch_Linux_from_existing_Linux#Creating_a_chroot
227 mkarchchroot() {
228 local tarball mirror
229 mirror=https://mirrors.edge.kernel.org/archlinux/iso/latest/
230 tarball=$(curl -s $mirror | sed -nr 's/.*"(archlinux-bootstrap-.*-x86_64.tar.gz)".*/\1/p')
231 wget -O /tmp/arch.tar.gz https://mirrors.edge.kernel.org/archlinux/iso/latest/$tarball
232 s mkdir -p /nocow/schroot/arch
233 cd _/nocow/schroot/arch
234 s sed -i '/## United States/,/^$/s,^#,,' etc/pacman.d/mirrorlist
235 # error: could not determine cachedir mount point /var/cache/pacman/pkg
236 s sed -i /^CheckSpace/d etc/pacman.conf
237 chroot . /bin/bash -s <<'EOF'
238 pacman-key --init
239 pacman-key --populate archlinux
240 pacman -Syyu
241 EOF
242 # example of building an aur package:
243 # pacman -Sy base-devel wget
244 # useradd -m iank
245 # f=$target/etc/sudoers
246 # line='iank ALL=(ALL) NOPASSWD: ALL'
247 # if [[ ! -e $f ]] || ! grep -xF "$line" $f; then
248 # echo "$line" >> $f
249 # fi
250 # su iank
251 # wget https://aur.archlinux.org/cgit/aur.git/snapshot/anbox-image-gapps.tar.gz
252 # tar xzf anbox-image-gapps.tar.gz
253 # cd anbox-image-gapps
254 # makepkg -s
255 }
256
257
258 # clock back in to timetrack from last entry
259 tback() {
260 sqlite3 /p/.timetrap.db "update entries set end = NULL where id = (select max(id) from entries);"
261 }
262
263 # sshfs example:
264 # s sshfs bu@$host:/bu/home/md /bu/mnt -o reconnect,ServerAliveInterval=20,ServerAliveCountMax=30 -o allow_other
265
266 eqgo() {
267 enn -M $(exiqgrep -i)
268 }
269 eqgo1() {
270 enn -M $(exiqgrep -i|h1)
271 }
272
273
274 gnupload(){
275 /a/f/gnulib/build-aux/gnupload "$@"
276 }
277
278 abrowserrmcompat() {
279 local f
280 ngset
281 f=(/p/c/firefox*/compatibility.ini)
282 if (( ${#f[@]} )); then
283 rm ${f[@]}
284 fi
285 ngreset
286 }
287 ngset() {
288 if shopt nullglob >/dev/null; then
289 ngreset=false
290 else
291 shopt -s nullglob
292 ngreset=true
293 fi
294 }
295 ngreset() {
296 if $ngreset; then
297 shopt -u nullglob
298 fi
299 }
300
301 checkre() {
302 s checkrestart -b /a/bin/ds/checkrestart-blacklist -pv
303 }
304
305 cp-blocked-domains-to-brains() {
306 cp /a/f/ans/roles/exim/files/mx/simple/etc/exim4/bad-sender_domains /a/f/brains/sysadmin/kb/blocked_email_domains.mdwn
307 }
308 cp-blocked-domains-to-ansible() {
309 cp /a/f/brains/sysadmin/kb/blocked_email_domains.mdwn /a/f/ans/roles/exim/files/mx/simple/etc/exim4/bad-sender_domains
310 }
311
312
313 anki() {
314 # crashes on adding new cards in t9
315 schroot -c buster -- anki
316 }
317
318 acat() {
319 ngset
320 hrcat /m/md/alerts/{cur,new}/*
321 ngreset
322 hr; echo bk; hr
323 ssh bk.b8.nz "shopt -s nullglob; hrcat /m/md/INBOX/new/* /m/md/INBOX/cur/*"
324 }
325 aclear() {
326 ngset
327 rm -f /m/md/alerts/{cur,new}/*
328 ngreset
329 ssh bk.b8.nz "shopt -s nullglob; rm -f /m/md/INBOX/new/* /m/md/INBOX/cur/*"
330 system-status _
331 }
332
333 alerts() {
334 find /var/local/cron-errors /home/iank/cron-errors /sysd-mail-once-state -type f
335 }
336 ralerts() { # remote alerts
337 local ret shell
338 # this list is duplicated in check-remote-mailqs
339 for h in bk je li frodo kwwg x3wg x2wg kdwg sywg; do
340 echo $h:
341 shell="ssh $h"
342 if [[ $HOSTNAME == "${h%wg}" ]]; then
343 shell=
344 fi
345 ret=0
346 $shell find /var/local/cron-errors /home/iank/cron-errors /sysd-mail-once-state -type f || ret=$?
347 if (( ret )); then
348 echo ret:$ret
349 fi
350 done
351 }
352
353 ap() {
354 # pushd in case current directory has an ansible.cfg file
355 pushd /a/xans >/dev/null
356 ansible-playbook -v -l ${1:- $(hostname -f)} site.yml
357 popd >/dev/null
358 }
359 aw() {
360 pushd /a/work/ans >/dev/null
361 time ansible-playbook -v -i inventory adhoc.yml "$@"
362 popd >/dev/null
363 }
364 ad() {
365 pushd /a/bin/distro-setup/a >/dev/null
366 ansible-playbook site.yml "$@"
367 popd >/dev/null
368 }
369
370 astudio() {
371 # googling android emulator libGL error: failed to load driver: r600
372 # lead to http://stackoverflow.com/a/36625175/14456
373 export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1
374 /a/opt/android-studio/bin/studio.sh "$@" &r;
375 }
376
377 # note, to check for glue records
378 # First, find some the .org nameservers:
379 # dig +trace iankelling.org
380 # then, query one:
381 # dig ns1.iankelling.org @b0.org.afilias-nst.org.
382
383 # Now, compare for a domain that does have glue records setup (note the A
384 # and AAAA records in ADDITIONAL SECTION, those are glue records like the
385 # one I'm asking for):
386
387 # $ dig ns1.gnu.org @b0.org.afilias-nst.org.
388
389 # todo: make sm pull/push use systemd instead of the journal cat command
390 bbk() { # btrbk wrapper
391 local ret=0
392 c /
393 local active=true
394 systemctl is-active btrbk.timer || active=false
395 if $active; then
396 ser stop btrbk.timer
397 fi
398 btrbk_is_active=$(systemctl is-active btrbk.service ||:)
399 case $btrbk_is_active in
400 inactive|failed) : ;;
401 *)
402 echo "bbk: error: systemctl is-active btrbk.service output: $btrbk_is_active"
403 if $active; then ser start btrbk.timer; fi
404 return 1
405 ;;
406 esac
407 # run latest
408 install-my-scripts
409 # todo: consider changing this to srun and having the args come
410 # from a file like /etc/default/btrbk, like is done in exim
411 s jrun btrbk-run "$@"
412 if $active; then
413 if (( ret )); then
414 echo bbk: WARNING: btrbk.timer not restarted due to failure
415 else
416 ser start btrbk.timer
417 fi
418 fi
419 return $ret
420 }
421
422 faimon() {
423 fai-monitor | pee cat "fai-monitor-gui -"
424 }
425
426 bfg() { java -jar /a/opt/bfg-1.12.14.jar "$@"; }
427
428 bigclock() {
429 xclock -digital -update 1 -face 'arial black-80:bold'
430 }
431
432 nnn() { /a/opt/nnn -H "$@"; }
433
434 locat() { # log-once cat
435 local files
436 ngset
437 files=(/var/local/cron-errors/* /home/iank/cron-errors/* /sysd-mail-once-state/*)
438 case ${#files[@]} in
439 0) : ;;
440 1)
441 echo ${files[0]}
442 head ${files[0]}
443 ;;
444 *)
445 head ${files[@]}
446 ;;
447 esac
448 ngreset
449 }
450
451 # duplicated somewhat below.
452 jrun() { # journal run. run args, log to journal, tail and grep the journal.
453 # Note, an alternative without systemd would be something like ts.
454 # Note, I tried using systemd-cat, but this seems obviously better,
455 # and that seemed to have a problem exiting during a systemctl daemon-reload
456 local cmd_name jr_pid s
457 ret=0
458 cmd_name=${1##*/}
459 cmd=$1
460 if [[ $cmd != /* ]]; then
461 cmd=$(which $1)
462 fi
463 journalctl -qn2 -f -u "$cmd_name" &
464 # Guess of time needed to avoid missing initial lines.
465 # .5 was not reliable. 1 was not reliable. 2 was not reliable
466 sleep 3
467 # We kill this in prompt-command for the case that we ctrl-c the
468 # systemd-cat. i dont know any way to trap ctrl-c and still run the
469 # normal action for it. There might be a way, unsure.
470 jr_pid=$!
471 # note, we could have a version that does system --user, but if for example
472 # it does sudo ssh, that will leave a process around that we can't kill
473 # and it will leave the unit hanging around in a failed state needing manual
474 # killing of the process.
475 m s systemd-run --uid $(id -u) --gid $(id -g) \
476 -E SSH_AUTH_SOCK=/run/openssh_agent \
477 --unit "$cmd_name" --wait --collect "$cmd" "${@:2}" || ret=$?
478 # This justs lets the journal output its last line
479 # before the prompt comes up.
480 sleep .5
481 kill $jr_pid &>/dev/null ||:
482 unset jr_pid
483 fg &>/dev/null ||:
484 }
485 # service run, and watch the output
486 srun() {
487 local unit
488 ret=0
489 unit=$1
490 journalctl -qn2 -f -u $unit &
491 systemctl start $unit
492 sleep 2
493 kill $jr_pid &>/dev/null ||:
494 unset jr_pid
495 fg &>/dev/null ||:
496 }
497
498 sm() {
499 local tmp keyhash
500 c /
501 # run latest
502 keyhash=$(s ssh-keygen -lf /root/.ssh/home | awk '{print $2}')
503 tmp=$(s ssh-add -l | awk '$2 == "'$keyhash'"')
504 if [[ ! $tmp ]]; then
505 s ssh-add /root/.ssh/home
506 fi
507 install-my-scripts
508 s jrun switch-mail-host "$@"
509 return $ret
510 }
511
512 # shellcheck disable=SC2120
513 lipush() {
514 # note, i had --delete-excluded, but that deletes all files in --exclude-from on
515 # the remote site, which doesn't make sense, so not sure why i had it.
516 local p a
517 # excluding emacs for now
518 #p=(/a/opt/{emacs-debian11{,-nox},mu,emacs} /a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts})
519 p=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts})
520 a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes"
521 ret=0
522 for h in li je bk; do
523 m s rsync "$@" $a ${p[@]} /p/c/machine_specific/$h root@$h.b8.nz:/
524 ## only li is debian11
525 #p[0]=/a/opt/emacs-trisuqel10
526 #p[1]=/a/opt/emacs-trisquel10-nox
527 done
528 m s rsync "$@" -ahviSAXPH root@li.b8.nz:/a/h/proposed-comments/ /a/h/proposed-comments || ret=$?
529 return $ret
530 }
531 bkpush() { # no emacs. for running faster.
532 p=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts})
533 a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes"
534 ret=0
535 m rsync "$@" $a ${p[@]} /p/c/machine_specific/bk root@bk.b8.nz:/ || ret=$?
536 return $ret
537 }
538 jepush() { # no emacs. for running faster.
539 p=(/a/bin /a/exe /a/h /a/c /p/c/machine_specific/vps{,.hosts})
540 a="-ahviSAXPH --specials --devices --delete --relative --exclude-from=/p/c/li-rsync-excludes"
541 ret=0
542 m rsync "$@" $a ${p[@]} /p/c/machine_specific/je root@je.b8.nz:/ || ret=$?
543 return $ret
544 }
545
546 bindpush() {
547 dsign iankelling.org expertpathologyreview.com zroe.org amnimal.ninja
548 lipush
549 for h in li bk; do
550 m sl $h <<'EOF'
551 source ~/.bashrc
552 m dnsup
553 EOF
554 done
555 }
556 bindpushb8() {
557 lipush
558 for h in li bk; do
559 m sl $h <<'EOF'
560 source ~/.bashrc
561 m dnsb8
562 EOF
563 done
564 }
565
566 dnsup() {
567 conflink -f
568 m ser reload named
569 }
570 dnsb8() {
571 local f=/var/lib/bind/db.b8.nz
572 m ser stop named
573 m sleep 1
574 m sudo rm -fv $f.jnl
575 m sudo install -m 644 -o bind -g bind /p/c/machine_specific/vps/bind-initial/db.b8.nz $f
576 m ser restart named
577 }
578 dnsecgen() {
579 # keys generated like this
580 # because of https://ftp.isc.org/isc/dnssec-guide/dnssec-guide.pdf
581 # https://blog.apnic.net/2019/05/23/how-to-deploying-dnssec-with-bind-and-ubuntu-server/
582
583 # key length is longer than that guide because
584 # we are using those at fsf and when old key lengths
585 # become insecure, I want some extra time to update.
586 # dnsecgen (in brc2)
587
588 local zone=$1
589 dnssec-keygen -a RSASHA256 -b 2048 $zone
590 dnssec-keygen -f KSK -a RSASHA256 -b 4096 $zone
591 for f in K$zone.*.key; do
592 # eg Kb8.nz.+008+47995.key tag=47995
593 # in dnsimple, you add the long string from this.
594 # in gandi, you add the long string from the .key file,
595 # then see that the digest matches the ds.
596 echo "tag is the number after DS"
597 dnssec-dsfromkey -a SHA-256 $f
598 done
599 # For b8.nz, we let bind read the keys and sign, and
600 # right now they have root ownership, so let them
601 # get group read.
602 chmod g+r *.private
603 }
604 dsign() {
605 # create .signed file
606 # note: full paths probably not needed.
607 local arg
608 for arg; do
609 local zone=${arg#db.}
610 local dir=/p/c/machine_specific/vps/filesystem/var/lib/bind
611 dnssec-signzone -S -e +31536000 -o $zone -K $dir -d $dir $dir/db.$zone
612 done
613 }
614
615
616 #### begin bitcoin related things
617 btc() {
618 local f=/etc/bitcoin/bitcoin.conf
619 # importprivkey will timeout if using the default of 15 mins.
620 # upped it to 1 hour.
621 bitcoin-cli -rpcclienttimeout=60000 -$(s grep rpcuser= $f) -$(s grep rpcpassword= $f) "$@"
622 }
623 btcusd() { # $1 btc in usd
624 local price
625 price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
626 printf "$%s\n" "$price"
627 if [[ $1 ]]; then
628 printf "$%.2f\n" "$(echo "scale=4; $price * $1"| bc -l)"
629 fi
630 }
631 usdbtc() { # $1 usd in btc
632 local price
633 price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
634 printf "$%s\n" "$price"
635 if [[ $1 ]]; then
636 # 100 mil satoshi / btc. 8 digits after the 1.
637 printf "%.8f btc\n" "$(echo "scale=10; $1 / $price "| bc -l)"
638 fi
639 }
640 satoshi() { # $1 satoshi in usd
641 local price
642 price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
643 price=$(echo "scale=10; $price * 0.00000001"| bc -l)
644 printf "$%f\n" "$price"
645 if [[ $1 ]]; then
646 printf "$%.2f\n" "$(echo "scale=10; $price * $1"| bc -l)"
647 fi
648 }
649 #### end bitcoin related things
650
651
652
653 cbfstool () { /a/opt/coreboot/build/cbfstool "$@"; }
654
655
656 cgpl()
657 {
658 if (($#)); then
659 cp /a/bin/data/COPYING "$@"
660 else
661 cp /a/bin/data/COPYING .
662 fi
663 }
664
665 capache()
666 {
667 if (($#)); then
668 cp /a/bin/data/LICENSE "$@"
669 else
670 cp /a/bin/data/LICENSE .
671 fi
672 }
673
674 chrome() {
675 if type -p chromium &>/dev/null; then
676 cmd=chromium
677 else
678 cd /
679 cmd="schroot -c bullseye chromium"
680 CHROMIUM_FLAGS='--enable-remote-extensions' $cmd &r
681 fi
682 }
683
684
685 # do all tee.
686 # pipe to this, or just type like a shell
687 # todo: test this
688 dat() {
689 tee >(ssh frodo.b8.nz) >(ssh x2) >(ssh tp.b8.nz) >(ssh kw) >(ssh tp.b8.nz)
690 }
691 da() { # do all
692 local host
693 for host in x2 kw tp.b8.nz x3.b8.nz frodo.b8.nz; do
694 ssh $host "$@"
695 done
696 }
697
698
699 debian_pick_mirror () {
700 # netselect-apt finds a fast mirror.
701 # but we need to replace the mirrors ourselves,
702 # because it doesnt do that. best it can do is
703 # output a basic sources file
704 # here we get the server it found, get the main server we use
705 # then substitute all instances of one for the other in the sources file
706 # and backup original to /etc/apt/sources.list-original.
707 # this is idempotent. the only way to identify debian sources is to
708 # note the original server, so we put it in a comment so we can
709 # identify it later.
710 local file
711 file=$(mktemp -d)/f # safe way to get file name without creating one
712 sudo netselect-apt -o "$file" || return 1
713 url=$(grep ^\\w $file | head -n1 | awk '{print $2}')
714 sudo cp -f /etc/apt/sources.list /etc/apt/sources.list-original
715 sudo sed -ri "/http.us.debian.org/ s@( *[^ #]+ +)[^ ]+([^#]+).*@\1$url\2# http.us.debian.org@" /etc/apt/sources.list
716 sudo apt-get update
717 }
718 digme() {
719 digdiff @ns{1,2}.iankelling.org "$@"
720 }
721
722 tsr() { # ts run
723 "$@" |& ts || return $?
724 }
725
726 dup() {
727 local ran_d
728 ran_d=false
729 system-status _
730 case $PS1 in
731 *[\ \]]D\ *)
732 pushd /
733 /b/ds/distro-begin |& ts || return $?
734 /b/ds/distro-end |& ts || return $?
735 popd
736 ran_d=true
737 ;;&
738 *[\ \]]DB\ *)
739 pushd /
740 /b/ds/distro-begin |& ts || return $?
741 popd
742 ran_d=true
743 ;;
744 *[\ \]]DE\ *)
745 pushd /
746 /b/ds/distro-end |& ts || return $?
747 popd
748 ran_d=true
749 ;;&
750 *CONFLINK*)
751 if ! $ran_d; then
752 conflink
753 fi
754 ;;
755 esac
756 system-status _
757 }
758
759 envload() { # load environment from a previous: export > file
760 local file=${1:-$HOME/.${USER}_env}
761 eval "$(export | sed 's/^declare -x/export -n/')"
762 while IFS= read -r line; do
763 # declare -x makes variables local to a function
764 eval ${line/#declare -x/export}
765 done < "$file"
766 }
767
768 failfunc() { asdf a b c; }
769 failfunc2() { failfunc d e f; }
770
771 # one that comes with distros is too old for newer devices
772 fastboot() {
773 /a/opt/android-platform-tools/fastboot "$@";
774 }
775
776 kdecd() { /usr/lib/x86_64-linux-gnu/libexec/kdeconnectd; }
777
778 bat() {
779 cat /sys/class/power_supply/BAT0/capacity
780 }
781
782 # List of apps to install/update
783 # Create from existing manually installed apps by doing
784 # fdroidcl update
785 # fdroidcl search -i, then manually removing
786 # automatically installed/preinstalled apps
787
788 #
789 # # my attempt at recovering from boot loop:
790 # # in that case, boot to recovery (volume up, home button, power, let go of power after samsun logo)
791 # # then
792 # mount /dev/block/mmcblk0p12 /data
793 # cd /data
794 # find -iname '*appname*'
795 # rm -rf FOUND_DIRS
796 # usually good enough to just rm -rf /data/app/APPNAME
797 #
798 # currently broken:
799 # # causes replicant to crash
800 # org.quantumbadger.redreader
801 # org.kde.kdeconnect_tp
802
803 # not broke, but wont work without gps
804 #com.zoffcc.applications.zanavi
805 # not broke, but not using atm
806 #com.nutomic.syncthingandroid
807 # # doesn\'t work on replicant
808 #net.sourceforge.opencamera
809 #
810 fdroid_pkgs=(
811 net.mullvad.mullvadvpn
812 org.schabi.newpipe
813 io.github.subhamtyagi.lastlauncher
814 io.anuke.mindustry
815 com.biglybt.android.client
816 de.marmaro.krt.ffupdater
817 me.ccrama.redditslide
818 org.fedorahosted.freeotp
819 at.bitfire.davdroid
820 com.alaskalinuxuser.justnotes
821 com.artifex.mupdf.viewer.app
822 com.danielkim.soundrecorder
823 com.fsck.k9
824 com.ichi2.anki
825 com.jmstudios.redmoon
826 com.jmstudios.chibe
827 org.kde.kdeconnect_tp
828 com.notecryptpro
829 com.termux
830 cz.martykan.forecastie
831 de.danoeh.antennapod
832 de.blinkt.openvpn
833 de.marmaro.krt.ffupdater
834 eu.siacs.conversations
835 free.rm.skytube.oss
836 im.vector.alpha # riot
837 info.papdt.blackblub
838 me.tripsit.tripmobile
839 net.gaast.giggity
840 net.minetest.minetest
841 net.osmand.plus
842 org.isoron.uhabits
843 org.linphone
844 org.gnu.icecat
845 org.smssecure.smssecure
846 org.yaaic
847 sh.ftp.rocketninelabs.meditationassistant.opensource
848 )
849 # https://forum.xda-developers.com/android/software-hacking/wip-selinux-capable-superuser-t3216394
850 # for maru,
851 #me.phh.superuser
852
853 fdup() {
854 local -A installed updated
855 local p
856 # tried putting this in go buildscript cronjob,
857 # but it failed with undefined: os.UserCacheDir. I expect its due to
858 # an environment variable missing, but its easier just to stick it here.
859 m go get -u mvdan.cc/fdroidcl || return 1
860 m fdroidcl update
861 if fdroidcl search -u | grep ^org.fdroid.fdroid; then
862 fdroidcl install org.fdroid.fdroid
863 sleep 5
864 m fdroidcl update
865 fi
866 for p in $(fdroidcl search -i| grep -o "^\S\+"); do
867 installed[$p]=true
868 done
869 for p in $(fdroidcl search -u| grep -o "^\S\+"); do
870 updated[$p]=false
871 done
872 for p in ${fdroid_pkgs[@]}; do
873 if ! ${installed[$p]:-false}; then
874 m fdroidcl install $p
875 # sleeps are just me being paranoid since replicant has a history of crashing when certain apps are installed
876 sleep 5
877 fi
878 done
879 for p in ${!installed[@]}; do
880 if ! ${updated[$p]:-true}; then
881 m fdroidcl install $p
882 sleep 5
883 fi
884 done
885 }
886
887 firefox-default-profile() {
888 key=Default value=1 section=$1
889 file=/p/c/subdir_files/.mozilla/firefox/profiles.ini
890 sed -ri "/^ *$key/d" "$file"
891 sed -ri "/ *\[$section\]/,/^ *\[[^]]+\]/{/^\s*$key[[:space:]=]/d};/ *\[$section\]/a $key=$value" "$file"
892 }
893 fdhome() { #firefox default home profile
894 firefox-default-profile Profile0
895 }
896
897 fdwork() {
898 firefox-default-profile Profile4
899 }
900
901 ff() {
902 if type -P firefox &>/dev/null; then
903 firefox "$@"
904 else
905 iceweasel "$@"
906 fi
907 }
908
909 fn() {
910 firefox -P alt "$@" >/dev/null 2>&1
911 }
912
913
914 fsdiff () {
915 local missing=false
916 local dname="${PWD##*/}"
917 local m="/a/tmp/$dname-missing"
918 local d="/a/tmp/$dname-diff"
919 [[ -e $d ]] && rm "$d"
920 [[ -e $m ]] && rm "$m"
921 local msize=0
922 local fsfile
923 while read -r line; do
924 fsfile="$1${line#.}"
925 if [[ -e "$fsfile" ]]; then
926 md5diff "$line" "$fsfile" && tee -a "/a/tmp/$dname-diff" <<< "$fsfile $line"
927 else
928 missing=true
929 echo "$line" >> "$m"
930 msize=$((msize + 1))
931 fi
932 done < <(find . -type f )
933 if $missing; then
934 echo "$m"
935 (( msize <= 100 )) && cat $m
936 fi
937 }
938 fsdiff-test() {
939 # expected output, with different tmp dirs
940 # /tmp/tmp.HDPbwMqdC9/c/d ./c/d
941 # /a/tmp/tmp.qLDkYxBYPM-missing
942 # ./b
943 cd $(mktemp -d)
944 echo ok > a
945 echo nok > b
946 mkdir c
947 echo ok > c/d
948 local x
949 x=$(mktemp -d)
950 mkdir $x/c
951 echo different > $x/c/d
952 echo ok > $x/a
953 fsdiff $x
954 }
955 rename-test() {
956 # test whether missing files were renamed, generally for use with fsdiff
957 # $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir
958 # echos non-renamed files
959 local x y found
960 unset sums
961 for x in "$2"/*; do
962 { sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null
963 done
964 while read -r line; do
965 { missing_sum=$(md5sum < "$line") ; } 2>/dev/null
966 renamed=false
967 for x in "${sums[@]}"; do
968 if [[ $missing_sum == "$x" ]]; then
969 renamed=true
970 break
971 fi
972 done
973 $renamed || echo "$line"
974 done < "$1"
975 return 0
976 }
977
978 feh() {
979 # F = fullscren, z = random, Z = auto zoom
980 command feh -FzZ "$@"
981 }
982
983
984
985 fw() {
986 firefox -P default "$@" >/dev/null 2>&1
987 }
988
989 gitian() {
990 git config user.email ian@iankelling.org
991 }
992
993 # at least in flidas, things rely on gpg being gpg1
994 gpg() {
995 if type -P gpg2 &>/dev/null; then
996 command gpg2 "$@"
997 else
998 command gpg "$@"
999 fi
1000 }
1001
1002 gse() {
1003 local email=ian@iankelling.org
1004 git send-email --notes "--envelope-sender=<$email>" \
1005 --suppress-cc=self "$@"
1006 }
1007
1008 gup() { /a/f/gnulib/build-aux/gnupload "$@"; }
1009
1010 dejagnu() { /a/opt/dejagnu/dejagnu "$@"; }
1011
1012 hstatus() {
1013 # do git status on published repos.
1014 c /a/bin/githtml
1015 for x in *; do
1016 cd $(readlink -f $x)/..
1017 status=$(i status -s) || pwd
1018 if [[ $status ]]; then
1019 hr
1020 echo $x
1021 printf "%s\n" "$status"
1022 fi
1023 cd /a/bin/githtml
1024 done
1025 }
1026
1027 # work log
1028 wlog() {
1029 local day now i
1030 for (( i=0; i<60; i++ )); do
1031 day=$( date +%F -d @$((EPOCHSECONDS - 86400*i )) )
1032 date "+%a %b %d" -d @$((EPOCHSECONDS - 86400*i )) | tr '\n' ' '
1033 /a/opt/timetrap/bin/t d -ftotal -s $day -e $day all -m '^w|lunch$'
1034 done
1035 }
1036 to() { t out -a "$@"; }
1037 ti() { t in -a "$@"; }
1038 tl() {
1039 to "$*"
1040 t s lunch
1041 t in -a "$*"
1042 m t out -a $(date +%F.%T -d @$(( $(date -d "$(echo $*|sed 's/[_.]/ /g')" +%s) + 60*45 )) )
1043 t s w
1044 }
1045
1046 arbttlog() { arbtt-dump "$@" | grep -v '( )\|Current Desktop' | sed -rn '/^[^ ]/{N;s/^(.{21})([0-9]*)[0-9]{3}m.*\(\*/\1\2/;s/^(.{21})[0-9]*.*\(\*/\1/;s/\n//;p}' ; }
1047
1048 idea() {
1049 /a/opt/idea-IC-163.7743.44/bin/idea.sh "$@" &r
1050 }
1051
1052 ilogs() {
1053 ssh root@iankelling.org "cd /var/lib/znc/moddata/log/iank/freenode/ && hr && for x in \#$1/*; do base=\${x##*/}; files=(); for f in $@; do tmp=\#\$f/\$base; if [[ -e \$tmp ]]; then files+=(\#\$f/\$base); fi; done; sed \"s/^./\${base%log}/\" \${files[@]}|sort -n; hr; done"
1054 }
1055
1056 ilog() {
1057 chan=${1:-#fsfsys}
1058 # use * instead of -r since that does sorted order
1059 ssh root@iankelling.org "for n in freenode libera; do cd /var/lib/znc/moddata/log/iank/\$n/$chan && hr && for x in *; do echo \$x; sed \"s/^./\${x%log}/\" \$x; hr; done; done" | less +G
1060 }
1061
1062 o() {
1063 if type gio &> /dev/null ; then
1064 gio open "$@"
1065 elif type gvfs-open &> /dev/null ; then
1066 gvfs-open "$@"
1067 else
1068 xdg-open "$@"
1069 fi
1070 # another alternative is run-mailcap
1071 }
1072 ccomp xdg-open o
1073
1074 # jfilter() {
1075 # grep -Evi -e "^(\S+\s+){4}(sudo|sshd|cron)\[\S*:" \
1076 # -e "^(\S+\s+){4}systemd\[\S*: (starting|started) (btrfsmaintstop|dynamicipupdate|spamd dns bug fix cronjob|rss2email)\.*$"
1077 # }
1078 # jtail() {
1079 # journalctl -n 10000 -f "$@" | jfilter
1080 # }
1081 # jr() { journalctl "$@" | jfilter | less ; }
1082 # jrf() { journalctl -n 200 -f "$@" | jfilter; }
1083
1084 jr() { journalctl "$@" ; }
1085 jrf() { journalctl -n 200 -f "$@" ; }
1086
1087
1088 ccomp journalctl jtail jr jrf
1089
1090 kff() { # keyboardio firmware flash. you must hold down the tilde key
1091 pushd /a/opt/Model01-Firmware
1092 # if we didn't want this yes hack, then remove "shell read" from
1093 # /a/opt/Kaleidoscope/etc/makefiles/sketch.mk
1094 yes $'\n' | VERBOSE=1 make flash
1095 popd
1096 }
1097
1098 wgkey() {
1099 local umask_orig name
1100 if (( $# != 1 )); then
1101 e expected 1 arg >&2
1102 return 1
1103 fi
1104 name=$1
1105 umask_orig=$(umask)
1106 umask 0077
1107 wg genkey | tee $name-priv.key | wg pubkey > $name-pub.key
1108 umask $umask_orig
1109 }
1110 wghole() {
1111 if (( $# != 2 )); then
1112 e expected 2 arg of hostname, ip suffix >&2
1113 return 1
1114 fi
1115 local host ipsuf umask_orig
1116 host=$1
1117 ipsuf=$2
1118 mkdir -p /p/c/machine_specific/$host/filesystem/etc/wireguard
1119 cd /p/c/machine_specific/$host/filesystem/etc/wireguard
1120 umask_orig=$(umask)
1121 umask 0077
1122 wg genkey | tee hole-priv.key | wg pubkey > hole-pub.key
1123 cat >wghole.conf <<EOF
1124 [Interface]
1125 # contents hole-priv.key
1126 PrivateKey = $(cat hole-priv.key)
1127 ListenPort = 1194
1128 Address = 10.8.0.$ipsuf/24
1129 # https://dev.to/tangramvision/what-they-don-t-tell-you-about-setting-up-a-wireguard-vpn-1h2g
1130 # ||: makes the systemd service not fail due to the failed command
1131 PostUp = ping -c1 10.8.0.1 ||:
1132
1133 [Peer]
1134 # li. called wgmail on that server
1135 PublicKey = CTFsje45qLAU44AbX71Vo+xFJ6rt7Cu6+vdMGyWjBjU=
1136 AllowedIPs = 10.8.0.0/24
1137 Endpoint = 72.14.176.105:1194
1138 PersistentKeepalive = 25
1139 EOF
1140 umask $umask_orig
1141 # old approach. systemd seems to work fine and cleaner.
1142 rm -f ../network/interfaces.d/wghole
1143 cedit -q $host /p/c/machine_specific/li/filesystem/etc/wireguard/wgmail.conf <<EOF || [[ $? == 1 ]]
1144 [Peer]
1145 PublicKey = $(cat hole-pub.key)
1146 AllowedIPs = 10.8.0.$ipsuf/32
1147 EOF
1148 cd - >/dev/null
1149 }
1150
1151
1152 mns() { # mount namespace
1153 ns=$1
1154 shift
1155 s mkdir -p /root/mount_namespaces
1156 if ! sudo mountpoint /root/mount_namespaces >/dev/null; then
1157 m sudo mount --bind /root/mount_namespaces /root/mount_namespaces
1158 fi
1159 m sudo mount --make-private /root/mount_namespaces
1160 if [[ ! -e /root/mount_namespaces/$ns ]]; then
1161 m sudo touch /root/mount_namespaces/$ns
1162 fi
1163 if ! sudo mountpoint /root/mount_namespaces/$ns >/dev/null; then
1164 m sudo unshare --propagation slave --mount=/root/mount_namespaces/$ns /bin/true
1165 fi
1166 m sudo -E /usr/bin/nsenter --mount=/root/mount_namespaces/$ns "$@"
1167 }
1168
1169 mnsr() { # mns run
1170 local ns=$1
1171 shift
1172 mns $ns sudo -u iank -E env "PATH=$PATH" "$@"
1173 }
1174
1175 mnsnonet() {
1176 ns=$1
1177 if ! s ip netns list | grep -Fx nonet &>/dev/null; then
1178 s ip netns add nonet
1179 fi
1180 mns $ns --net=/var/run/netns/nonet sudo -E -u iank /bin/bash
1181 lomh
1182 }
1183
1184
1185 lom() {
1186 # l = the loopback device
1187 local l base
1188 if [[ $1 == /* ]]; then
1189 base=${1##*/}
1190 fs_file=$1
1191 if mns $base mountpoint -q /mnt/$base; then
1192 return 0
1193 fi
1194 l=$(losetup -j $fs_file | sed -rn 's/^([^ ]+): .*/\1/p' | head -n1 ||:)
1195 if [[ ! $l ]]; then
1196 l=$(sudo losetup -f)
1197 m sudo losetup $l $fs_file
1198 fi
1199 if ! sudo cryptsetup status /dev/mapper/$base &>/dev/null; then
1200 if ! sudo cryptsetup luksOpen $l $base; then
1201 m sudo losetup -d $l
1202 return 1
1203 fi
1204 fi
1205 m sudo mkdir -p /mnt/$base
1206 m mns $base mount /dev/mapper/$base /mnt/$base
1207 m mns $base chown $USER:$USER /mnt/$base
1208 lomh
1209 else
1210 base=$1
1211 if mns $base mountpoint /mnt/$base &>/dev/null; then
1212 m mns $base umount /mnt/$base
1213 fi
1214 if sudo cryptsetup status /dev/mapper/$base &>/dev/null; then
1215 if ! m sudo cryptsetup luksClose /dev/mapper/$base; then
1216 echo lom: failed cryptsetup luksClose /dev/mapper/$base
1217 return 1
1218 fi
1219 fi
1220 l=$(losetup -l --noheadings | awk '$6 ~ /\/'$base'$/ {print $1}')
1221 if [[ $l ]]; then
1222 m sudo losetup -d $l
1223 else
1224 echo lom: warning: no loopback device found
1225 fi
1226 fi
1227 }
1228
1229 # mu personality. for original, just run mp. for 2, run mp 2.
1230 # this is partly duplicated in mail-setup
1231 mp() {
1232 local dead=false
1233 for s in {1..5}; do
1234 if ! killall mu; then
1235 dead=true
1236 break
1237 fi
1238 sleep 1
1239 done
1240 if ! $dead; then
1241 echo error: mu not dead
1242 m psg mu
1243 return 1
1244 fi
1245 suf=$1
1246 set -- /m/mucache ~/.cache/mu /m/.mu ~/.config/mu
1247 while (($#)); do
1248 target=$1$suf
1249 f=$2
1250 shift 2
1251 if [[ -e $f && ! -L $f ]]; then
1252 m rm -rf $f
1253 fi
1254 m ln -sf -T $target $f
1255 done
1256 }
1257
1258 # these might need a mu index or something added.
1259 mbenable() {
1260 local mb=$1
1261 dst=/m/4e/$mb
1262 src=/m/md/$mb
1263 [[ -e $src ]] || { echo "src:$src does not exist"; return 1; }
1264 m mv -T $src $dst
1265 m ln -s -T $dst $src
1266 }
1267 mb2enable() {
1268 local mb
1269 for mb; do
1270 dst=/m/4e2/$mb
1271 link=/m/md/$mb
1272 src=/m/md/$mb
1273 if [[ ! -e $src || -L $src ]]; then
1274 src=/m/4e/$mb
1275 fi
1276 [[ -e $src ]] || { echo "src:$src does not exist"; return 1; }
1277 m mv -T $src $dst
1278 m ln -sf -T $dst $link
1279 done
1280 }
1281 mbdisable() {
1282 local mb=$1
1283 dst=/m/md/$mb
1284 src=/m/4e/$mb
1285 set -x
1286 [[ -e $src ]] || { set +x; return 1; }
1287 if [[ -L $dst ]]; then rm $dst; fi
1288 mv -T $src $dst
1289 set +x
1290 }
1291 mb2disable() {
1292 local mb=$1
1293 dst=/m/md/$mb
1294 src=/m/4e2/$mb
1295 set -x
1296 [[ -e $src ]] || { set +x; return 1; }
1297 if [[ -L $dst ]]; then rm $dst; fi
1298 mv -T $src $dst
1299 set +x
1300 }
1301
1302
1303 mdt() {
1304 markdown "$1" >/tmp/mdtest.html
1305 firefox /tmp/mdtest.html
1306 }
1307
1308 mo() { xset dpms force off; } # monitor off
1309
1310 mpvd() {
1311 mpv --profile=d "$@";
1312 }
1313 # mpv all media files in . or $1
1314 mpvm() {
1315 local -a extensions arg
1316 # get page source of https://en.wikipedia.org/w/index.php?title=Video_file_format&action=edit
1317 # into /a/x.log, then
1318 # grep '^| *\.' /a/x.log | sed 's/| *//;s/,//g'
1319 extensions=(
1320 .webm
1321 .mkv
1322 .flv
1323 .flv
1324 .vob
1325 .ogv .ogg
1326 .drc
1327 .gif
1328 .gifv
1329 .mng
1330 .avi
1331 .MTS .M2TS .TS
1332 .mov .qt
1333 .wmv
1334 .yuv
1335 .rm
1336 .rmvb
1337 .viv
1338 .asf
1339 .amv
1340 .mp4 .m4p .m4v
1341 .mpg .mp2 .mpeg .mpe .mpv
1342 .mpg .mpeg .m2v
1343 .m4v
1344 .svi
1345 .3gp
1346 .3g2
1347 .mxf
1348 .roq
1349 .nsv
1350 )
1351 arg=("(" -iname "*${extensions[0]}")
1352 for (( i=1 ; i < ${#extensions[@]}; i++ )); do
1353 arg+=(-o -iname "*${extensions[i]}")
1354 done
1355 arg+=(")")
1356 dir=${1:-.}
1357 # debug:
1358 #find $dir "${arg[@]}" -size +1M
1359 find $dir "${arg[@]}" -size +1M -exec mpv --profile=d '{}' +
1360 }
1361 mpvs() {
1362 mpv --profile=s "$@";
1363 }
1364
1365 myirc() {
1366 if [[ ! $1 ]]; then
1367 set -- fsf-office
1368 fi
1369 local d1 d2
1370 d=( /var/lib/znc/moddata/log/iank/{freenode,libera} )
1371 # use * instead of -r since that does sorted order
1372 ssh root@iankelling.org "for f in ${d[@]}; do cd \$f/#$1; grep '\<iank.*' *; done" | cut --complement -c12-16
1373 }
1374 mypidgin() {
1375 c /p/c/.purple/logs/jabber/iank@fsf.org/office@conference.fsf.org.chat
1376 for x in *.html; do html2text -o ${x%.html}.txt $x; done;
1377 grep -A1 ') iank:' *.txt | sed -r 's/^(.{10})[^ ]*\.txt:\(?([^ ]*)[[:space:]](..). iank:/\1_\2_\3/;s/^[^ ]*\.txt-//;/^--$/d;s/^[^ ]*\.txt:\((.{2}).(.{2}).(.{4}) (.{8}) (.{2})\)?/\3-\1-\2_\4_\5/' | sed -n 'x;1d;0~2{G;s/\n/ /;p};${x;p}'
1378 }
1379 allmyirc() {
1380 local d
1381 d=/var/lib/znc/moddata/log/iank/freenode
1382 ssh root@iankelling.org "cd $d; find . -mtime -60 -type f -exec grep '\<iank.*' {} +" | sed -r 's,^..([^/]*)/(.{11})(.{5})(.{8}).,\2\4 \1,' | sort
1383 }
1384
1385 mygajim() {
1386 local time time_sec time_pretty
1387 sqlite3 -separator ' ' /p/c/subdir_files/.local/share/gajim/logs.db "select time, message from logs where contact_name = 'iank' and jid_id = 17;" | while read -r time l; do
1388 case $time in
1389 16*) : ;;
1390 *) continue ;;
1391 esac
1392 if ! time_pretty=$(date +%F.%R -d @$time); then
1393 echo bad time: $time
1394 return 1
1395 fi
1396 echo $time_pretty "$l"
1397 time_sec=${time%%.*}
1398 # only look at the last 18 days. generally just use this for timesheet.
1399 if (( time_sec < EPOCHSECONDS - 60 * 60 * 24 * 18 )); then break; fi
1400 done
1401 }
1402
1403 allmygajim() {
1404 sqlite3 -separator ' ' /p/c/subdir_files/.local/share/gajim/logs.db "select time, message from logs where contact_name = 'iank'" | less
1405 }
1406
1407 gajlogs() {
1408 sqlite3 -separator ' ' /p/c/subdir_files/.local/share/gajim/logs.db "select time, message from logs" | less
1409 }
1410
1411 net-dev-info() {
1412 e "lspci -nnk|gr -iA2 net"
1413 lspci -nnk|gr -iA2 net
1414 hr
1415 e "s lshw -C network"
1416 hr
1417 sudo lshw -C network
1418 }
1419
1420 nk() {
1421 ser stop NetworkManager
1422 ser disable NetworkManager
1423 ser stop NetworkManager-wait-online.service
1424 ser disable NetworkManager-wait-online.service
1425 ser stop dnsmasq
1426 sudo resolvconf -d NetworkManager
1427 # ser start dnsmasq
1428 sudo ifup br0
1429 }
1430 ngo() {
1431 sudo ifdown br0
1432 ser start NetworkManager
1433 sleep 4
1434 sudo nmtui-connect
1435 }
1436
1437 otp() {
1438 oathtool --totp -b "$*" | xclip -selection clipboard
1439 }
1440 j() {
1441 "$@" |& pee "xclip -r -selection clipboard"
1442 }
1443
1444
1445 pakaraoke() {
1446 # from http://askubuntu.com/questions/456021/remove-vocals-from-mp3-and-get-only-instrumentals
1447 pactl load-module module-ladspa-sink sink_name=Karaoke master=alsa_output.usb-Audioengine_Audioengine_D1-00.analog-stereo plugin=karaoke_1409 label=karaoke control=-30
1448 }
1449
1450 pfind() { #find *$1* in $PATH
1451 [[ $# != 1 ]] && { echo requires 1 argument; return 1; }
1452 local pathArray
1453 IFS=: pathArray=($PATH); unset IFS
1454 find "${pathArray[@]}" -iname "*$1*"
1455 }
1456
1457 pick-trash() {
1458 # trash-restore lists everything that has been trashed at or below CWD
1459 # This picks out files just in CWD, not subdirectories,
1460 # which also match grep $1, usually use $1 for a time string
1461 # which you get from running restore-trash once first
1462 local name x ask
1463 local nth=1
1464 # last condition is to not ask again for ones we skipped
1465 while name="$( echo | restore-trash | gr "$PWD/[^/]\+$" | gr "$1" )" \
1466 && [[ $name ]] && (( $(wc -l <<<"$name") >= nth )); do
1467 name="$(echo "$name" | head -n $nth | tail -n 1 )"
1468 read -r -p "$name [Y/n] " ask
1469 if [[ ! $ask || $ask == [Yy] ]]; then
1470 x=$( echo "$name" | gr -o "^\s*[0-9]*" )
1471 echo $x | restore-trash > /dev/null
1472 elif [[ $ask == [Nn] ]]; then
1473 nth=$((nth+1))
1474 else
1475 return
1476 fi
1477 done
1478 }
1479
1480
1481 pub() {
1482 rld /a/h/_site/ li:/var/www/iankelling.org/html
1483 }
1484
1485
1486 pumpa() {
1487 # fixes the menu bar in xmonad. this won\'t be needed when xmonad
1488 # packages catches up on some changes in future (this is written in
1489 # 4/2017)
1490 #
1491 # geekosaur: so youll want to upgrade to xmonad 0.13 or else use a
1492 # locally modified XMonad.Hooks.ManageDocks that doesnt set the
1493 # work area; turns out it\'s impossible to set correctly if you are
1494 # not a fully EWMH compliant desktop environment
1495 #
1496 # geekosaur: chrome shows one failure mode, qt/kde another, other
1497 # gtk apps a third, ... I came up with a setting that works for me
1498 # locally but apparently doesnt work for others, so we joined the
1499 # other tiling window managers in giving up on setting it at all
1500 #
1501 xprop -root -remove _NET_WORKAREA
1502 command pumpa & r
1503 }
1504
1505 # reviewboard, used at my old job
1506 #rbpipe() { rbt post -o --diff-filename=- "$@"; }
1507 #rbp() { rbt post -o "$@"; }
1508
1509 rebr() {
1510 sudo ifdown br0
1511 sudo ifup br0
1512 }
1513
1514
1515 # only run on MAIL_HOST. simpler to keep this on one system.
1516 r2eadd() { # usage: name url
1517 # initial setup of rss2email:
1518 # r2e new r2e@iankelling.org
1519 # that initializes files, and sets default email.
1520 # symlink to the config doesnt work, so I copied it to /p/c
1521 # and then use cli option to specify explicit path.
1522 # Only option changed from default config is to set
1523 # force-from = True
1524 #
1525 # or else for a few feeds, the from address is set by the feed, and
1526 # if I fail delivery, then I send a bounce message to that from
1527 # address, which makes me be a spammer.
1528
1529 r2e add $1 "$2" $1@r2e.iankelling.org
1530 # get up to date and dont send old entries now:
1531 r2e run --no-send $1
1532 }
1533 r2e() { command r2e -d /p/c/rss2email.json -c /p/c/rss2email.cfg "$@"; }
1534
1535 rspicy() { # usage: HOST DOMAIN
1536 # connect to spice vm remote host. use vspicy for local host
1537 local port
1538 # shellcheck disable=SC2087
1539 port=$(ssh $1<<EOF
1540 sudo virsh dumpxml $2|grep "<graphics.*type='spice'" | \
1541 sed -rn "s/.*port='([0-9]+).*/\1/p"
1542 EOF
1543 )
1544 if [[ $port ]]; then
1545 spicy -h $1 -p $port
1546 else
1547 echo "error: no port found. check that the domain is running."
1548 fi
1549 }
1550
1551
1552 scssl() {
1553 # s gem install scss-lint
1554 pushd /a/opt/thoughtbot-guides
1555 git pull --stat
1556 popd
1557 scss-lint -c /a/opt/thoughtbot-guides/style/sass/.scss-lint.yml "$@"
1558 }
1559
1560 skbrc() {
1561 sk -e 2120,245 /b/ds/brc /b/ds/brc2
1562 }
1563
1564 skaraoke() {
1565 local tmp out
1566 out=${2:-${1%.*}.sh}
1567 tmp=$(mktemp -d)
1568 script -t -c "mpv --no-config --no-resume-playback --no-terminal --no-audio-display '$1'" $tmp/typescript 2>$tmp/timing
1569 # todo, the current sleep seems pretty good, but it
1570 # would be nice to have an empirical measurement, or
1571 # some better wait to sync up.
1572 #
1573 # note: --loop-file=no prevents it from hanging if you have that
1574 # set to inf the mpv config.
1575 # --loop=no prevents it from exit code 3 due to stdin if you
1576 # had it set to inf in mpv config.
1577 #
1578 # args go to mpv, for example --volume=80, 50%
1579 cat >$out <<EOFOUTER
1580 #!/bin/bash
1581 trap "trap - TERM && kill 0" INT TERM ERR; set -e
1582 ( sleep .2; scriptreplay <( cat <<'EOF'
1583 $(cat $tmp/timing)
1584 EOF
1585 ) <( cat <<'EOF'
1586 $(cat $tmp/typescript)
1587 EOF
1588 ))&
1589 base64 -d - <<'EOF'| mpv --loop=no --loop-file=no --no-terminal --no-audio-display "\$@" -
1590 $(base64 "$1")
1591 EOF
1592 kill 0
1593 EOFOUTER
1594 rm -r $tmp
1595 chmod +x $out
1596 }
1597
1598 smeld() { # ssh meld usage host1 host2 file
1599 meld <(ssh $1 cat $3) <(ssh $2 cat $3)
1600 }
1601
1602 spd() {
1603 PATH=/usr/local/spdhackfix:$PATH command spd "$@"
1604 }
1605
1606 spamf() { # spamtest on FILE
1607 local spamcpre spamdpid
1608
1609 if (( $# != 1 )); then
1610 e spamtest error: expected 1 arg, filename >&2
1611 return 1
1612 fi
1613
1614 spamdpid=$(systemctl status spamassassin| sed -n '/^ *Main PID:/s/[^0-9]//gp')
1615 spamcpre="nsenter -t $spamdpid -n -m"
1616 s $spamcpre sudo -u Debian-exim spamassassin -t --cf='score PYZOR_CHECK 0' <"$1"
1617 }
1618
1619
1620 # mail related
1621 testmail() {
1622 declare -gi _seq; _seq+=1
1623 echo "test body" | m mail -s "test mail from $HOSTNAME, $_seq" "${@:-root@localhost}"
1624 # for testing to send from an external address, you can do for example
1625 # -fian@iank.bid -aFrom:ian@iank.bid web-6fnbs@mail-tester.com
1626 # note in exim, you can retry a deferred message
1627 # s exim -M MSG_ID
1628 # MSG_ID is in /var/log/exim4/mainlog, looks like 1ccdnD-0001nh-EN
1629 }
1630
1631 # to test sieve, use below command. for fsf mail, see offlineimap-sync script
1632 # make modifications, then copy to live file, use -eW to actually modify mailbox
1633 #
1634 # Another option is to use sieve-test SCRIPT MAIL_FILE. note,
1635 # sieve-test doesnt know about envelopes, Im not sure if sieve-filter does.
1636
1637 # sieve with output filter. arg is mailbox, like INBOX.
1638 # This depends on dovecot conf, notably mail_location in /etc/dovecot/conf.d/10-mail.conf
1639
1640 # always run this first, edit the test files, then run the following
1641 testsieve() {
1642 sieve-filter ~/sieve/maintest.sieve ${1:-INBOX} delete 2> >(head; tail) >/tmp/testsieve.log && sed -rn '/^Performed actions:/,/^[^ ]/{/^ /p}' /tmp/testsieve.log | sort | uniq -c
1643 }
1644 runsieve() {
1645 c ~/sieve; cp personal{test,}.sieve; cp lists{test,}.sieve; cp personalend{test,}.sieve
1646 sieve-filter -eWv ~/sieve/maintest.sieve ${1:-INBOX} delete &> /tmp/testsieve.log
1647 sed -r '/^info: filtering:/{h;d};/^info: msgid=$/N;/^info: msgid=.*left message in mailbox [^ ]+$/d;/^info: msgid=/{H;g};/^info: message kept in source mailbox.$/d' /tmp/testsieve.log
1648 }
1649
1650 # usage:
1651 # alertme SUBJECT
1652 # printf "subject\nbody\n" | alertme
1653 alertme() {
1654 if [[ -t 0 ]]; then
1655 exim -t <<EOF
1656 From: alertme@b8.nz
1657 To: alerts@iankelling.org
1658 Subject: $*
1659 EOF
1660 else
1661 read sub
1662 { cat <<EOF
1663 From: alertme@b8.nz
1664 To: alerts@iankelling.org
1665 Subject: $sub
1666
1667 EOF
1668 cat
1669 } | exim -t
1670 fi
1671 }
1672 daylertme() {
1673 if [[ -t 0 ]]; then
1674 exim -t <<EOF
1675 From: alertme@b8.nz
1676 To: daylert@iankelling.org
1677 Subject: $*
1678 EOF
1679 else
1680 read sub
1681 { cat <<EOF
1682 From: alertme@b8.nz
1683 To: daylert@iankelling.org
1684 Subject: $sub
1685
1686 EOF
1687 cat
1688 } | exim -t
1689 fi
1690 }
1691
1692 # alert when a page goes live. not urgent.
1693 alert200() {
1694 url="$1"
1695 tmpdir="$(mktemp -d)"
1696 cd $tmpdir
1697 while true; do
1698 if torsocks wget -q "$url"; then
1699 alertme $tmpdir
1700 fi
1701 sleep $(( 600 + RANDOM % 300 ))
1702 done
1703 }
1704
1705 # alert on changes to a webpage (just the base page that curl gets)
1706 # usage: weblert URL [SUBJECT...]
1707 weblert() {
1708 local u old new quiet
1709 quiet=false
1710 case $1 in
1711 # dont send a diff of the html. some html is not very readable
1712 -q) quiet=true
1713 shift
1714 ;;
1715 esac
1716 u="$1"
1717 shift
1718 subject="${*:-weblert}"
1719 old=$(curl -s "$u") ||:
1720 while true; do
1721 new=$(curl -s "$u") ||:
1722 if [[ $old && $new ]]; then
1723 if [[ $new != "$old" ]]; then
1724 if $quiet; then
1725 echo | daylertme "$subject"
1726 else
1727 diff <(printf "%s\n" "$old") <(printf "%s\n" "$new") | daylertme "$subject" ||:
1728 fi
1729 fi
1730 old="$new"
1731 fi
1732 sleep $(( 60 + RANDOM % 120 ))
1733 done
1734 }
1735
1736 torshell() {
1737 # per man torsocks
1738 source `type -p torsocks` on
1739 }
1740
1741 eless2() {
1742 less /var/log/exim4/mymain
1743 }
1744
1745
1746 # mail related
1747 testexim() {
1748 # testmail above calls sendmail, which is a link to exim/postfix.
1749 # its docs dont say a way of adding an argument
1750 # to sendmail to turn on debug output. We could make a wrapper, but
1751 # that is a pain. Exim debug args are documented here:
1752 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
1753 #
1754 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-building_and_installing_exim.html
1755 # note, for exim daemon, you can turn on debug options by
1756 # adding -d, etc to COMMONOPTIONS in
1757 # /etc/default/exim4
1758 #
1759 # to specify recipients other than those in to, cc, bcc, you can use the cli args, eg:
1760 # exim -t 'test@zroe.org, t2@zroe.org' <<'EOF'
1761 #
1762 # -t = get recipient from header
1763 exim -d -t <<'EOF'
1764 From: i@dmarctest.b8.nz
1765 To: mailman@dev.fsf.org
1766 Subject: test2
1767 Reply-to: rtest@iankelling.org
1768
1769 This is a test message.
1770 EOF
1771 }
1772
1773 # toggle keyboard
1774 tk() {
1775 # based on
1776 # https://askubuntu.com/questions/160945/is-there-a-way-to-disable-a-laptops-internal-keyboard
1777 id=$(xinput --list --id-only 'AT Translated Set 2 keyboard')
1778 if xinput list | grep -F '∼ AT Translated Set 2 keyboard' &>/dev/null; then
1779 echo enabling keyboard
1780 # find the first slave keyboard number, they are all the same in my output.
1781 # if they werent, worst case we would need to save the slave number somewhere
1782 # when it got disabled.
1783 slave=$(xinput list | sed -n 's/.*slave \+keyboard (\([0-9]*\)).*/\1/p' | head -n1)
1784 xinput reattach $id $slave
1785 else
1786 xinput float $id
1787 fi
1788 }
1789
1790 tm() {
1791 # timer in minutes
1792 # --no-config
1793 (sleep $(calc "$* * 60") && mpv --no-config --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
1794 }
1795
1796 trg() { transmission-remote-gtk & r; }
1797 trc() {
1798 # example, set global upload limit to 100 kilobytes:
1799 # trc -u 100
1800 TR_AUTH=":$(jq -r .profiles[0].password ~/.config/transmission-remote-gtk/config.json)" transmission-remote transmission.lan -ne "$@"
1801 }
1802
1803 trysleep() {
1804 retries="$1"
1805 sleepsecs="$2"
1806 shift 2
1807 for (( i=0; i < retries - 1; i++ )); do
1808 if "$@"; then
1809 return 0
1810 fi
1811 sleep $sleepsecs
1812 done
1813 "$@"
1814 }
1815
1816
1817 tu() {
1818 local s
1819 if [[ -e $1 && ! -w $1 || ! -w $(dirname "$1") ]]; then
1820 s=s;
1821 fi
1822 # full path for using in some initial setup steps
1823 $s /a/exe/teeu "$@"
1824 }
1825
1826 enn() {
1827 local ecmd pid
1828
1829 ecmd="/usr/sbin/exim4 -C /etc/exim4/my.conf"
1830 if ip a show veth1-mail &>/dev/null; then
1831 s $ecmd "$@"
1832 return
1833 fi
1834 pid=$(pgrep -f "/usr/sbin/exim4 -bd -q30m -C /etc/exim4/my.conf"|h1)
1835 m s nsenter -t $pid -n -m $ecmd "$@"
1836 }
1837
1838 # get pid of systemd service
1839 servicepid() {
1840 local pid unit
1841 unit="$1"
1842 pid=$(systemctl show --property MainPID --value "$unit")
1843 case $pid in
1844 [1-9]*) : ;;
1845 *)
1846 # 0 or empty. This file includes the MainPid, so I expect we
1847 # could just get this in the first place, but i don't know if that
1848 # is always the case.
1849 pid=$(head -n1 /sys/fs/cgroup/systemd/system.slice/${unit%.service}.service/cgroup.procs)
1850 ;;
1851 esac
1852 if [[ $pid ]]; then
1853 printf "%s\n" "$pid"
1854 else
1855 return 1
1856 fi
1857 }
1858
1859 sdnbash() { # systemd namespace bash
1860 local unit pid
1861 unit=$1
1862 pid=$(servicepid $unit)
1863 m sudo nsenter -t $pid -n -m sudo -u $USER -i bash
1864 }
1865
1866 sdncmd() { # systemd namespace cmd
1867 local unit pid
1868 unit=$1
1869 shift
1870 pid=$(servicepid $unit)
1871 m sudo nsenter -t $pid -n -m sudo -u $USER -i "$@"
1872 }
1873
1874
1875 mailnnbash() {
1876 sdnbash mailnn
1877 }
1878
1879 # we use wireguard now, use mailnnbash.
1880 # mailvpnbash() {
1881 # m sudo nsenter -t $(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*mail.conf") -n -m sudo -u $USER -i bash
1882 # }
1883
1884 eximbash() {
1885 local pid
1886 pid=$(pgrep -f "/usr/sbin/exim4 -bd -q30m -C /etc/exim4/my.conf"|h1)
1887 if [[ ! $pid ]]; then
1888 echo "eximbash: failed to find exim pid. systemctl -n 30 status exim4:"
1889 systemctl status exim4
1890 fi
1891 m sudo nsenter -t $pid -n -m
1892 }
1893 spamnn() {
1894 local spamdpid
1895 spamdpid=$(systemctl show --property MainPID --value spamassassin)
1896 m sudo nsenter -t $spamdpid -n -m sudo -u Debian-exim spamassassin "$@"
1897 }
1898 unboundbash() {
1899 m sudo nsenter -t $(systemctl status unbound| sed -n '/^ *Main PID:/s/[^0-9]//gp') -n -m sudo -u $USER -i bash
1900 }
1901
1902 nmtc() {
1903 s nmtui-connect "$@"
1904 }
1905
1906 mailnncheck() {
1907 local p pid ns mailnn
1908 # mailvpn would belong on the list if using openvpn
1909 for p in mailnn unbound dovecot spamassassin exim4 radicale; do
1910
1911
1912 pid=$(systemctl show --property MainPID --value $unit)
1913 case $pid in
1914 [1-9]*) : ;;
1915 *)
1916 # 0 or empty. This file includes the MainPid, so I expect we
1917 # could just get this in the first place, but i don't know if
1918 # that is always the case.
1919 pid=$(head -n1 /sys/fs/cgroup/systemd/system.slice/${unit%.service}.service/cgroup.procs)
1920 ;;
1921 esac
1922 echo p=$p pid=$pid
1923 if [[ ! $pid ]]; then
1924 echo failed to find pid for $p
1925 continue
1926 fi
1927 if ! ns=$(s readlink /proc/$pid/ns/net); then
1928 echo failed to find ns for $p pid=$pid
1929 continue
1930 fi
1931 if [[ $mailnn ]]; then
1932 if [[ $ns != "$mailnn" ]]; then
1933 echo "$p ns $ns != $mailnn"
1934 fi
1935 else
1936 mailnn=$ns
1937 fi
1938 done
1939
1940 }
1941
1942
1943 vpncmd() {
1944 m sudo -E env "PATH=$PATH" nsenter -t $(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*client.conf") -n "$@"
1945 }
1946
1947 vpni() {
1948 vpncmd sudo -u iank env "PATH=$PATH" "$@"
1949 }
1950 vpnbash() {
1951 vpncmd bash
1952 }
1953
1954
1955 vpn() {
1956 if [[ -e /lib/systemd/system/openvpn-client@.service ]]; then
1957 local vpn_service=openvpn-client
1958 else
1959 local vpn_service=openvpn
1960 fi
1961
1962 [[ $1 ]] || { echo need arg; return 1; }
1963 journalctl --unit=$vpn_service@$1 -f -n0 &
1964 # sometimes the journal doesnt open until after the vpn output
1965 # has happened. hoping this fixes that.
1966 sleep 1
1967 sudo systemctl start $vpn_service@$1
1968 # sometimes the ask-password agent does not work and needs a delay.
1969 sleep .5
1970 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=779240
1971 # noticed around 8-2017 after update from around stretch release
1972 # on debian testing, even though the bug is much older.
1973 sudo systemd-tty-ask-password-agent
1974 }
1975
1976 fixu() {
1977 ls -lad /run/user/1000
1978 s chmod 700 /run/user/1000; s chown iank.iank /run/user/1000
1979 }
1980
1981 # systemctl is-enabled / status / cat says nothing, instead theres
1982 # some obscure symlink. paths copied from man systemd.unit.
1983 # possibly also usefull, but incomplete, doesnt show units not loaded in memory:
1984 # seru list-dependencies --reverse --all UNIT
1985 sysd-deps() {
1986 local f
1987 local -a dirs search
1988 ngset
1989
1990 case $1 in
1991 u)
1992 search=(
1993 ~/.config/systemd/user.control/*
1994 $XDG_RUNTIME_DIR/systemd/user.control/*
1995 $XDG_RUNTIME_DIR/systemd/transient/*
1996 $XDG_RUNTIME_DIR/systemd/generator.early/*
1997 ~/.config/systemd/user/*
1998 /etc/systemd/user/*
1999 $XDG_RUNTIME_DIR/systemd/user/*
2000 /run/systemd/user/*
2001 $XDG_RUNTIME_DIR/systemd/generator/*
2002 ~/.local/share/systemd/user/*
2003 /usr/lib/systemd/user/*
2004 $XDG_RUNTIME_DIR/systemd/generator.late/*
2005 )
2006 ;;
2007 *)
2008 search=(
2009 /etc/systemd/system.control/*
2010 /run/systemd/system.control/*
2011 /run/systemd/transient/*
2012 /run/systemd/generator.early/*
2013 /etc/systemd/system/*
2014 /etc/systemd/systemd.attached/*
2015 /run/systemd/system/*
2016 /run/systemd/systemd.attached/*
2017 /run/systemd/generator/*
2018 /lib/systemd/system/*
2019 /run/systemd/generator.late/*
2020 )
2021 ;;
2022 esac
2023 for f in "${search[@]}"; do
2024 [[ -d $f ]] || continue
2025 case $f in
2026 *.requires|*.wants)
2027 dirs+=("$f")
2028 ;;
2029 esac
2030 done
2031 # dirs is just so we write out the directory names, ls does it when there is 2 or more dirs.
2032 case ${#dirs[@]} in
2033 1)
2034 echo "${dirs[0]}:"
2035 ll "${dirs[@]}"
2036 ;;
2037 0) : ;;
2038 *)
2039 ll "${dirs[@]}"
2040 ;;
2041 esac
2042 ngreset
2043 }
2044
2045 fixvpndns() {
2046 local link istls
2047 read _ link _ istls < <(resolvectl dnsovertls tunfsf)
2048 case $istls in
2049 yes|no) : ;;
2050 *) echo fixvpndns error: unexpected istls value: $istls >&2; return 1 ;;
2051 esac
2052 s busctl call org.freedesktop.resolve1 /org/freedesktop/resolve1 org.freedesktop.resolve1.Manager SetLinkDNSOverTLS is $link no
2053 }
2054
2055 vpnoff() {
2056 [[ $1 ]] || { echo need arg; return 1; }
2057 if [[ -e /lib/systemd/system/openvpn-client@.service ]]; then
2058 local vpn_service=openvpn-client
2059 else
2060 local vpn_service=openvpn
2061 fi
2062 sudo systemctl stop $vpn_service@$1
2063 }
2064 vpnoffc() { # vpn off client
2065 ser stop openvpn-client-tr@client
2066 }
2067 vpnc() {
2068 ser start openvpn-client-tr@client
2069 }
2070
2071
2072 vspicy() { # usage: VIRSH_DOMAIN
2073 # connect to vms made with virt-install
2074 spicy -p $(sudo virsh dumpxml "$1"|grep "<graphics.*type='spice'"|\
2075 sed -r "s/.*port='([0-9]+).*/\1/")
2076 }
2077
2078 wian() {
2079 cat-new-files /m/4e/INBOX/new
2080 }
2081
2082 wtr() { curl wttr.in/boston; }
2083
2084 xevkb() { xev -event keyboard; }
2085
2086 # * misc stuff
2087
2088 vrun() {
2089 printf "running: %s\n" "$*"
2090 "$@"
2091 }
2092
2093 f=/a/f/ansible-configs/files/common/etc/fsf-workstation-bashrc.sh
2094 if [[ -e $f ]]; then
2095 # shellcheck disable=SC1090
2096 source $f
2097 fi
2098
2099 electrum() {
2100 # https://electrum.readthedocs.io/en/latest/tor.html
2101 # https://github.com/spesmilo/electrum-docs/issues/129
2102 s rsync -ptog --chown bitcoin:bitcoin ~/.Xauthority /var/lib/bitcoind/.Xauthority
2103 sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/electrum-4.2.1-x86_64.AppImage -p socks5:localhost:9050
2104 }
2105 monero() {
2106 sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/monero-gui-v0.17.3.2/monero-wallet-gui
2107 }
2108
2109
2110 reset-konsole() {
2111 # we also have a file in /a/c/...konsole...
2112 local f=$HOME/.config/konsolerc
2113 setini DefaultProfile profileian.profile "Desktop Entry" $f
2114 setini Favorites profileian.profile "Favorite Profiles" $f
2115 setini ShowMenuBarByDefault false KonsoleWindow $f
2116 setini TabBarPosition Top TabBar $f
2117 }
2118
2119 reset-sakura() {
2120 while read -r k v; do
2121 # shellcheck disable=SC2154
2122 setini $k $v sakura /a/c/subdir_files/.config/sakura/sakura.conf
2123 done <<'EOF'
2124 colorset1_back rgb(33,37,39)
2125 less_questions true
2126 audible_bell No
2127 visible_bell No
2128 disable_numbered_tabswitch true
2129 scroll_lines 10000000
2130 scrollbar true
2131 EOF
2132 }
2133
2134 # make a page of links found in the files $@. redirect output
2135 linkhtml() {
2136 gr -oh 'https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)' "$@" | \
2137 rev | sort -u | rev | sed 's,.*,<a href="\0">\0</a><br\>,'
2138 }
2139
2140 reset-xscreensaver() {
2141 # except for spash, i set these by setting gui options in
2142 # xscreensaver-command -demo
2143 # then finding the corresponding option in .xscreensaver
2144 # spash, i happened to notice in .xscreensaver
2145 #
2146 # dpmsOff, monitor doesnt come back on using old free software supported nvidia card
2147 cat > /home/iank/.xscreensaver <<'EOF'
2148 mode: blank
2149 dpmsEnabled: True
2150 dpmsStandby: 0:07:00
2151 dpmsSuspend: 0:08:00
2152 dpmsOff: 0:00:00
2153 timeout: 0:05:00
2154 lock: True
2155 lockTimeout: 0:06:00
2156 splash: False
2157 EOF
2158
2159 }
2160
2161
2162 # * stuff that makes sense to be at the end
2163 if [[ "$SUDOD" ]]; then
2164 # allow failure, for example if we are sudoing into a user with diffferent/lesser permissions.
2165 cd "$SUDOD" ||:
2166 unset SUDOD
2167 elif [[ -d /a ]] && [[ $PWD == "$HOME" ]] && [[ $- == *i* ]]; then
2168 cd /a
2169 OLDPWD=
2170 fi
2171
2172
2173
2174
2175 # for mitmproxy to get a newer python.
2176 # commented until i want to use it because it
2177 # noticably slows bash startup
2178 #
2179
2180 mypyenvinit () {
2181 if [[ $EUID == 0 || ! -e ~/.pyenv/bin ]]; then
2182 echo "error: dont be root. make sure pyenv is installed"
2183 return 1
2184 fi
2185 export PATH="$HOME/.pyenv/bin:$PATH"
2186 eval "$(pyenv init -)"
2187 eval "$(pyenv virtualenv-init -)"
2188 }
2189
2190
2191 export GOPATH=$HOME/go
2192 path-add $GOPATH/bin
2193 path-add /usr/local/go/bin
2194
2195 # I have the git repo and a release. either one should work.
2196 # I have both because I was trying to solve an issue that
2197 # turned out to be unrelated.
2198 # ARDUINO_PATH=/a/opt/Arduino/build/linux/work
2199
2200 ## i should have documented this...
2201 # based on https://github.com/keyboardio/Kaleidoscope
2202 export KALEIDOSCOPE_DIR=/a/opt/Kaleidoscope
2203
2204 # They want to be added to the start, but i think
2205 # that should be avoided unless we really need it.
2206 path-add --end ~/.npm-global
2207
2208
2209 path-add --end $HOME/.cargo/bin
2210
2211 if type -P rg &>/dev/null; then
2212 # --no-messages because of annoying errors on broken symlinks
2213 # -z = search .gz etc files
2214 # -. = search dotfilesq
2215 rg() { command rg -. -z --no-messages -L -i -M 900 --no-ignore "$@" || return $?; }
2216 #fails if not exist. ignore
2217 complete -r rg 2>/dev/null ||:
2218 else
2219 alias rg=grr
2220 fi
2221
2222
2223
2224 # taken from default changes to bashrc and bash_profile
2225 path-add --end --ifexists $HOME/.rvm/bin
2226 # also had ruby bin dir, but moved that to environment.sh
2227 # so its included in overall env
2228
2229
2230 export BASEFILE_DIR=/a/bin/fai-basefiles
2231
2232 #export ANDROID_HOME=/a/opt/android-home
2233 # https://f-droid.org/en/docs/Installing_the_Server_and_Repo_Tools/
2234 #export USE_SDK_WRAPPER=yes
2235 #PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
2236
2237 # didnt get drush working, if I did, this seems like the
2238 # only good thing to include for it.
2239 # Include Drush completion.
2240 # if [ -f "/home/ian/.drush/drush.complete.sh" ] ; then
2241 # source /home/ian/.drush/drush.complete.sh
2242 # fi
2243
2244
2245 # best practice
2246 unset IFS
2247
2248 # https://wiki.archlinux.org/index.php/Xinitrc#Autostart_X_at_login
2249 # i added an extra condition as gentoo xorg guide says depending on
2250 # $DISPLAY is fragile.
2251 if [[ ! $DISPLAY && $XDG_VTNR == 1 ]] && shopt -q login_shell && isarch; then
2252 exec startx
2253 fi
2254
2255
2256 # ensure no bad programs appending to this file will have an affect
2257 return 0