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