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