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