7d94df1fc12e1011bc08fe6adaf3078fbad89a78
[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 mnsnonet() {
1159 ns=$1
1160 if ! s ip netns list | grep -Fx nonet &>/dev/null; then
1161 s ip netns add nonet
1162 fi
1163 mns $ns --net=/var/run/netns/nonet sudo -E -u iank /bin/bash
1164 }
1165
1166
1167 lom() {
1168 local l base
1169 if [[ $1 == /* ]]; then
1170 base=${1##*/}
1171 if mns $base mountpoint -q /mnt/$base; then
1172 return 0
1173 fi
1174 l=$(losetup -j $1 | sed -rn 's/^([^ ]+): .*/\1/p' | head -n1 ||:)
1175 if [[ ! $l ]]; then
1176 l=$(sudo losetup -f)
1177 m sudo losetup $l $1
1178 fi
1179 if ! sudo cryptsetup status /dev/mapper/$base &>/dev/null; then
1180 if ! sudo cryptsetup luksOpen $l $base; then
1181 m sudo losetup -d $l
1182 return 1
1183 fi
1184 fi
1185 m sudo mkdir -p /mnt/$base
1186 m mns $base mount /dev/mapper/$base /mnt/$base
1187 m mns $base chown $USER:$USER /mnt/$base
1188 else
1189 base=$1
1190 if mns $base mountpoint /mnt/$base &>/dev/null; then
1191 m mns $base umount /mnt/$base
1192 fi
1193 if sudo cryptsetup status /dev/mapper/$base &>/dev/null; then
1194 if ! m sudo cryptsetup luksClose /dev/mapper/$base; then
1195 echo lom: failed cryptsetup luksClose /dev/mapper/$base
1196 return 1
1197 fi
1198 fi
1199 l=$(losetup -l --noheadings | awk '$6 ~ /\/'$1'$/ {print $1}')
1200 if [[ $l ]]; then
1201 m sudo losetup -d $l
1202 else
1203 echo lom: warning: no loopback device found
1204 fi
1205 fi
1206 }
1207
1208 # mu personality. for original, just run mp. for 2, run mp 2.
1209 # this is partly duplicated in mail-setup
1210 mp() {
1211 local dead=false
1212 for s in {1..5}; do
1213 if ! killall mu; then
1214 dead=true
1215 break
1216 fi
1217 sleep 1
1218 done
1219 if ! $dead; then
1220 echo error: mu not dead
1221 m psg mu
1222 return 1
1223 fi
1224 suf=$1
1225 set -- /m/mucache ~/.cache/mu /m/.mu ~/.config/mu
1226 while (($#)); do
1227 target=$1$suf
1228 f=$2
1229 shift 2
1230 if [[ -e $f && ! -L $f ]]; then
1231 m rm -rf $f
1232 fi
1233 m ln -sf -T $target $f
1234 done
1235 }
1236
1237 # these might need a mu index or something added.
1238 mbenable() {
1239 local mb=$1
1240 dst=/m/4e/$mb
1241 src=/m/md/$mb
1242 [[ -e $src ]] || { echo "src:$src does not exist"; return 1; }
1243 m mv -T $src $dst
1244 m ln -s -T $dst $src
1245 }
1246 mb2enable() {
1247 local mb
1248 for mb; do
1249 dst=/m/4e2/$mb
1250 link=/m/md/$mb
1251 src=/m/md/$mb
1252 if [[ ! -e $src || -L $src ]]; then
1253 src=/m/4e/$mb
1254 fi
1255 [[ -e $src ]] || { echo "src:$src does not exist"; return 1; }
1256 m mv -T $src $dst
1257 m ln -sf -T $dst $link
1258 done
1259 }
1260 mbdisable() {
1261 local mb=$1
1262 dst=/m/md/$mb
1263 src=/m/4e/$mb
1264 set -x
1265 [[ -e $src ]] || { set +x; return 1; }
1266 if [[ -L $dst ]]; then rm $dst; fi
1267 mv -T $src $dst
1268 set +x
1269 }
1270
1271
1272 mdt() {
1273 markdown "$1" >/tmp/mdtest.html
1274 firefox /tmp/mdtest.html
1275 }
1276
1277 mo() { xset dpms force off; } # monitor off
1278
1279 mpvd() {
1280 mpv --profile=d "$@";
1281 }
1282 # mpv all media files in . or $1
1283 mpvm() {
1284 local -a extensions arg
1285 # get page source of https://en.wikipedia.org/w/index.php?title=Video_file_format&action=edit
1286 # into /a/x.log, then
1287 # grep '^| *\.' /a/x.log | sed 's/| *//;s/,//g'
1288 extensions=(
1289 .webm
1290 .mkv
1291 .flv
1292 .flv
1293 .vob
1294 .ogv .ogg
1295 .drc
1296 .gif
1297 .gifv
1298 .mng
1299 .avi
1300 .MTS .M2TS .TS
1301 .mov .qt
1302 .wmv
1303 .yuv
1304 .rm
1305 .rmvb
1306 .viv
1307 .asf
1308 .amv
1309 .mp4 .m4p .m4v
1310 .mpg .mp2 .mpeg .mpe .mpv
1311 .mpg .mpeg .m2v
1312 .m4v
1313 .svi
1314 .3gp
1315 .3g2
1316 .mxf
1317 .roq
1318 .nsv
1319 )
1320 arg=("(" -iname "*${extensions[0]}")
1321 for (( i=1 ; i < ${#extensions[@]}; i++ )); do
1322 arg+=(-o -iname "*${extensions[i]}")
1323 done
1324 arg+=(")")
1325 dir=${1:-.}
1326 # debug:
1327 #find $dir "${arg[@]}" -size +1M
1328 find $dir "${arg[@]}" -size +1M -exec mpv --profile=d '{}' +
1329 }
1330 mpvs() {
1331 mpv --profile=s "$@";
1332 }
1333
1334 myirc() {
1335 if [[ ! $1 ]]; then
1336 set -- fsf-office
1337 fi
1338 local d1 d2
1339 d=( /var/lib/znc/moddata/log/iank/{freenode,libera} )
1340 # use * instead of -r since that does sorted order
1341 ssh root@iankelling.org "for f in ${d[@]}; do cd \$f/#$1; grep '\<iank.*' *; done" | cut --complement -c12-16
1342 }
1343 mypidgin() {
1344 c /p/c/.purple/logs/jabber/iank@fsf.org/office@conference.fsf.org.chat
1345 for x in *.html; do html2text -o ${x%.html}.txt $x; done;
1346 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}'
1347 }
1348 allmyirc() {
1349 local d
1350 d=/var/lib/znc/moddata/log/iank/freenode
1351 ssh root@iankelling.org "cd $d; find . -mtime -60 -type f -exec grep '\<iank.*' {} +" | sed -r 's,^..([^/]*)/(.{11})(.{5})(.{8}).,\2\4 \1,' | sort
1352 }
1353
1354 mygajim() {
1355 local time time_sec time_pretty
1356 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
1357 case $time in
1358 16*) : ;;
1359 *) continue ;;
1360 esac
1361 if ! time_pretty=$(date +%F.%R -d @$time); then
1362 echo bad time: $time
1363 return 1
1364 fi
1365 echo $time_pretty "$l"
1366 time_sec=${time%%.*}
1367 # only look at the last 18 days. generally just use this for timesheet.
1368 if (( time_sec < EPOCHSECONDS - 60 * 60 * 24 * 18 )); then break; fi
1369 done
1370 }
1371
1372 allmygajim() {
1373 sqlite3 -separator ' ' /p/c/subdir_files/.local/share/gajim/logs.db "select time, message from logs where contact_name = 'iank'" | less
1374 }
1375
1376 gajlogs() {
1377 sqlite3 -separator ' ' /p/c/subdir_files/.local/share/gajim/logs.db "select time, message from logs" | less
1378 }
1379
1380 net-dev-info() {
1381 e "lspci -nnk|gr -iA2 net"
1382 lspci -nnk|gr -iA2 net
1383 hr
1384 e "s lshw -C network"
1385 hr
1386 sudo lshw -C network
1387 }
1388
1389 nk() {
1390 ser stop NetworkManager
1391 ser disable NetworkManager
1392 ser stop NetworkManager-wait-online.service
1393 ser disable NetworkManager-wait-online.service
1394 ser stop dnsmasq
1395 sudo resolvconf -d NetworkManager
1396 # ser start dnsmasq
1397 sudo ifup br0
1398 }
1399 ngo() {
1400 sudo ifdown br0
1401 ser start NetworkManager
1402 sleep 4
1403 sudo nmtui-connect
1404 }
1405
1406 otp() {
1407 oathtool --totp -b "$*" | xclip -selection clipboard
1408 }
1409 j() {
1410 "$@" |& pee "xclip -r -selection clipboard"
1411 }
1412
1413
1414 pakaraoke() {
1415 # from http://askubuntu.com/questions/456021/remove-vocals-from-mp3-and-get-only-instrumentals
1416 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
1417 }
1418
1419 pfind() { #find *$1* in $PATH
1420 [[ $# != 1 ]] && { echo requires 1 argument; return 1; }
1421 local pathArray
1422 IFS=: pathArray=($PATH); unset IFS
1423 find "${pathArray[@]}" -iname "*$1*"
1424 }
1425
1426 pick-trash() {
1427 # trash-restore lists everything that has been trashed at or below CWD
1428 # This picks out files just in CWD, not subdirectories,
1429 # which also match grep $1, usually use $1 for a time string
1430 # which you get from running restore-trash once first
1431 local name x ask
1432 local nth=1
1433 # last condition is to not ask again for ones we skipped
1434 while name="$( echo | restore-trash | gr "$PWD/[^/]\+$" | gr "$1" )" \
1435 && [[ $name ]] && (( $(wc -l <<<"$name") >= nth )); do
1436 name="$(echo "$name" | head -n $nth | tail -n 1 )"
1437 read -r -p "$name [Y/n] " ask
1438 if [[ ! $ask || $ask == [Yy] ]]; then
1439 x=$( echo "$name" | gr -o "^\s*[0-9]*" )
1440 echo $x | restore-trash > /dev/null
1441 elif [[ $ask == [Nn] ]]; then
1442 nth=$((nth+1))
1443 else
1444 return
1445 fi
1446 done
1447 }
1448
1449
1450 pub() {
1451 rld /a/h/_site/ li:/var/www/iankelling.org/html
1452 }
1453
1454
1455 pumpa() {
1456 # fixes the menu bar in xmonad. this won\'t be needed when xmonad
1457 # packages catches up on some changes in future (this is written in
1458 # 4/2017)
1459 #
1460 # geekosaur: so youll want to upgrade to xmonad 0.13 or else use a
1461 # locally modified XMonad.Hooks.ManageDocks that doesnt set the
1462 # work area; turns out it\'s impossible to set correctly if you are
1463 # not a fully EWMH compliant desktop environment
1464 #
1465 # geekosaur: chrome shows one failure mode, qt/kde another, other
1466 # gtk apps a third, ... I came up with a setting that works for me
1467 # locally but apparently doesnt work for others, so we joined the
1468 # other tiling window managers in giving up on setting it at all
1469 #
1470 xprop -root -remove _NET_WORKAREA
1471 command pumpa & r
1472 }
1473
1474 # reviewboard, used at my old job
1475 #rbpipe() { rbt post -o --diff-filename=- "$@"; }
1476 #rbp() { rbt post -o "$@"; }
1477
1478 rebr() {
1479 sudo ifdown br0
1480 sudo ifup br0
1481 }
1482
1483
1484 # only run on MAIL_HOST. simpler to keep this on one system.
1485 r2eadd() { # usage: name url
1486 # initial setup of rss2email:
1487 # r2e new r2e@iankelling.org
1488 # that initializes files, and sets default email.
1489 # symlink to the config doesnt work, so I copied it to /p/c
1490 # and then use cli option to specify explicit path.
1491 # Only option changed from default config is to set
1492 # force-from = True
1493 #
1494 # or else for a few feeds, the from address is set by the feed, and
1495 # if I fail delivery, then I send a bounce message to that from
1496 # address, which makes me be a spammer.
1497
1498 r2e add $1 "$2" $1@r2e.iankelling.org
1499 # get up to date and dont send old entries now:
1500 r2e run --no-send $1
1501 }
1502 r2e() { command r2e -d /p/c/rss2email.json -c /p/c/rss2email.cfg "$@"; }
1503
1504 rspicy() { # usage: HOST DOMAIN
1505 # connect to spice vm remote host. use vspicy for local host
1506 local port
1507 # shellcheck disable=SC2087
1508 port=$(ssh $1<<EOF
1509 sudo virsh dumpxml $2|grep "<graphics.*type='spice'" | \
1510 sed -rn "s/.*port='([0-9]+).*/\1/p"
1511 EOF
1512 )
1513 if [[ $port ]]; then
1514 spicy -h $1 -p $port
1515 else
1516 echo "error: no port found. check that the domain is running."
1517 fi
1518 }
1519
1520
1521 scssl() {
1522 # s gem install scss-lint
1523 pushd /a/opt/thoughtbot-guides
1524 git pull --stat
1525 popd
1526 scss-lint -c /a/opt/thoughtbot-guides/style/sass/.scss-lint.yml "$@"
1527 }
1528
1529 skbrc() {
1530 sk -e 2120,245 /b/ds/brc /b/ds/brc2
1531 }
1532
1533 skaraoke() {
1534 local tmp out
1535 out=${2:-${1%.*}.sh}
1536 tmp=$(mktemp -d)
1537 script -t -c "mpv --no-config --no-resume-playback --no-terminal --no-audio-display '$1'" $tmp/typescript 2>$tmp/timing
1538 # todo, the current sleep seems pretty good, but it
1539 # would be nice to have an empirical measurement, or
1540 # some better wait to sync up.
1541 #
1542 # note: --loop-file=no prevents it from hanging if you have that
1543 # set to inf the mpv config.
1544 # --loop=no prevents it from exit code 3 due to stdin if you
1545 # had it set to inf in mpv config.
1546 #
1547 # args go to mpv, for example --volume=80, 50%
1548 cat >$out <<EOFOUTER
1549 #!/bin/bash
1550 trap "trap - TERM && kill 0" INT TERM ERR; set -e
1551 ( sleep .2; scriptreplay <( cat <<'EOF'
1552 $(cat $tmp/timing)
1553 EOF
1554 ) <( cat <<'EOF'
1555 $(cat $tmp/typescript)
1556 EOF
1557 ))&
1558 base64 -d - <<'EOF'| mpv --loop=no --loop-file=no --no-terminal --no-audio-display "\$@" -
1559 $(base64 "$1")
1560 EOF
1561 kill 0
1562 EOFOUTER
1563 rm -r $tmp
1564 chmod +x $out
1565 }
1566
1567 smeld() { # ssh meld usage host1 host2 file
1568 meld <(ssh $1 cat $3) <(ssh $2 cat $3)
1569 }
1570
1571 spd() {
1572 PATH=/usr/local/spdhackfix:$PATH command spd "$@"
1573 }
1574
1575 spend() {
1576 sudo systemctl suspend
1577 }
1578
1579 spamf() { # spamtest on FILE
1580 local spamcpre spamdpid
1581
1582 if (( $# != 1 )); then
1583 e spamtest error: expected 1 arg, filename >&2
1584 return 1
1585 fi
1586
1587 spamdpid=$(systemctl status spamassassin| sed -n '/^ *Main PID:/s/[^0-9]//gp')
1588 spamcpre="nsenter -t $spamdpid -n -m"
1589 s $spamcpre sudo -u Debian-exim spamassassin -t --cf='score PYZOR_CHECK 0' <"$1"
1590 }
1591
1592
1593 # mail related
1594 testmail() {
1595 declare -gi _seq; _seq+=1
1596 echo "test body" | m mail -s "test mail from $HOSTNAME, $_seq" "${@:-root@localhost}"
1597 # for testing to send from an external address, you can do for example
1598 # -fian@iank.bid -aFrom:ian@iank.bid web-6fnbs@mail-tester.com
1599 # note in exim, you can retry a deferred message
1600 # s exim -M MSG_ID
1601 # MSG_ID is in /var/log/exim4/mainlog, looks like 1ccdnD-0001nh-EN
1602 }
1603
1604 # to test sieve, use below command. for fsf mail, see offlineimap-sync script
1605 # make modifications, then copy to live file, use -eW to actually modify mailbox
1606 #
1607 # Another option is to use sieve-test SCRIPT MAIL_FILE. note,
1608 # sieve-test doesnt know about envelopes, Im not sure if sieve-filter does.
1609
1610 # sieve with output filter. arg is mailbox, like INBOX.
1611 # This depends on dovecot conf, notably mail_location in /etc/dovecot/conf.d/10-mail.conf
1612
1613 # always run this first, edit the test files, then run the following
1614 testsieve() {
1615 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
1616 }
1617 runsieve() {
1618 c ~/sieve; cp personal{test,}.sieve; cp lists{test,}.sieve; cp personalend{test,}.sieve
1619 sieve-filter -eWv ~/sieve/maintest.sieve ${1:-INBOX} delete &> /tmp/testsieve.log
1620 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
1621 }
1622
1623 # usage:
1624 # alertme SUBJECT
1625 # printf "subject\nbody\n" | alertme
1626 alertme() {
1627 if [[ -t 0 ]]; then
1628 exim -t <<EOF
1629 From: alertme@b8.nz
1630 To: alerts@iankelling.org
1631 Subject: $*
1632 EOF
1633 else
1634 read sub
1635 { cat <<EOF
1636 From: alertme@b8.nz
1637 To: alerts@iankelling.org
1638 Subject: $sub
1639
1640 EOF
1641 cat
1642 } | exim -t
1643 fi
1644 }
1645 daylertme() {
1646 if [[ -t 0 ]]; then
1647 exim -t <<EOF
1648 From: alertme@b8.nz
1649 To: daylert@iankelling.org
1650 Subject: $*
1651 EOF
1652 else
1653 read sub
1654 { cat <<EOF
1655 From: alertme@b8.nz
1656 To: daylert@iankelling.org
1657 Subject: $sub
1658
1659 EOF
1660 cat
1661 } | exim -t
1662 fi
1663 }
1664
1665 # alert when a page goes live. not urgent.
1666 alert200() {
1667 url="$1"
1668 tmpdir="$(mktemp -d)"
1669 cd $tmpdir
1670 while true; do
1671 if torsocks wget -q "$url"; then
1672 alertme $tmpdir
1673 fi
1674 sleep $(( 600 + RANDOM % 300 ))
1675 done
1676 }
1677
1678
1679 # mail related
1680 testexim() {
1681 # testmail above calls sendmail, which is a link to exim/postfix.
1682 # its docs dont say a way of adding an argument
1683 # to sendmail to turn on debug output. We could make a wrapper, but
1684 # that is a pain. Exim debug args are documented here:
1685 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
1686 #
1687 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-building_and_installing_exim.html
1688 # note, for exim daemon, you can turn on debug options by
1689 # adding -d, etc to COMMONOPTIONS in
1690 # /etc/default/exim4
1691 #
1692 # to specify recipients other than those in to, cc, bcc, you can use the cli args, eg:
1693 # exim -t 'test@zroe.org, t2@zroe.org' <<'EOF'
1694 #
1695 # -t = get recipient from header
1696 exim -d -t <<'EOF'
1697 From: i@dmarctest.b8.nz
1698 To: mailman@dev.fsf.org
1699 Subject: test2
1700 Reply-to: rtest@iankelling.org
1701
1702 This is a test message.
1703 EOF
1704 }
1705
1706 # toggle keyboard
1707 tk() {
1708 # based on
1709 # https://askubuntu.com/questions/160945/is-there-a-way-to-disable-a-laptops-internal-keyboard
1710 id=$(xinput --list --id-only 'AT Translated Set 2 keyboard')
1711 if xinput list | grep -F '∼ AT Translated Set 2 keyboard' &>/dev/null; then
1712 echo enabling keyboard
1713 # find the first slave keyboard number, they are all the same in my output.
1714 # if they werent, worst case we would need to save the slave number somewhere
1715 # when it got disabled.
1716 slave=$(xinput list | sed -n 's/.*slave \+keyboard (\([0-9]*\)).*/\1/p' | head -n1)
1717 xinput reattach $id $slave
1718 else
1719 xinput float $id
1720 fi
1721 }
1722
1723 tm() {
1724 # timer in minutes
1725 # --no-config
1726 (sleep $(calc "$* * 60") && mpv --no-config --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
1727 }
1728
1729 trg() { transmission-remote-gtk & r; }
1730 trc() {
1731 # example, set global upload limit to 100 kilobytes:
1732 # trc -u 100
1733 TR_AUTH=":$(jq -r .profiles[0].password ~/.config/transmission-remote-gtk/config.json)" transmission-remote transmission.lan -ne "$@"
1734 }
1735
1736 trysleep() {
1737 retries="$1"
1738 sleepsecs="$2"
1739 shift 2
1740 for (( i=0; i < retries - 1; i++ )); do
1741 if "$@"; then
1742 return 0
1743 fi
1744 sleep $sleepsecs
1745 done
1746 "$@"
1747 }
1748
1749
1750 tu() {
1751 local s
1752 if [[ -e $1 && ! -w $1 || ! -w $(dirname "$1") ]]; then
1753 s=s;
1754 fi
1755 # full path for using in some initial setup steps
1756 $s /a/exe/teeu "$@"
1757 }
1758
1759 enn() {
1760 local ecmd pid
1761
1762 ecmd="/usr/sbin/exim4 -C /etc/exim4/my.conf"
1763 if ip a show veth1-mail &>/dev/null; then
1764 s $ecmd "$@"
1765 return
1766 fi
1767 pid=$(pgrep -f "/usr/sbin/exim4 -bd -q30m -C /etc/exim4/my.conf"|h1)
1768 m s nsenter -t $pid -n -m $ecmd "$@"
1769 }
1770
1771 sdnbash() { # systemd namespace bash
1772 local unit=$1
1773 m sudo nsenter -t $(systemctl show --property MainPID --value $unit) -n -m sudo -u $USER -i bash
1774 }
1775
1776 mailnnbash() {
1777 m sudo nsenter -t $(systemctl show --property MainPID --value mailnn) -n -m sudo -u $USER -i bash
1778 }
1779
1780 mailvpnbash() {
1781 m sudo nsenter -t $(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*mail.conf") -n -m sudo -u $USER -i bash
1782 }
1783 eximbash() {
1784 local pid
1785 pid=$(pgrep -f "/usr/sbin/exim4 -bd -q30m -C /etc/exim4/my.conf"|h1)
1786 if [[ ! $pid ]]; then
1787 echo "eximbash: failed to find exim pid. systemctl -n 30 status exim4:"
1788 systemctl status exim4
1789 fi
1790 m sudo nsenter -t $pid -n -m
1791 }
1792 spamnn() {
1793 local spamdpid
1794 spamdpid=$(systemctl show --property MainPID --value spamassassin)
1795 m sudo nsenter -t $spamdpid -n -m sudo -u Debian-exim spamassassin "$@"
1796 }
1797 unboundbash() {
1798 m sudo nsenter -t $(systemctl status unbound| sed -n '/^ *Main PID:/s/[^0-9]//gp') -n -m sudo -u $USER -i bash
1799 }
1800
1801 mailnncheck() {
1802 local p pid ns mailnn
1803 # mailvpn would belong on the list if using openvpn
1804 for p in mailnn unbound dovecot spamassassin exim4 radicale; do
1805 case $p in
1806 exim4|radicale)
1807 pid=$(ps -eo pid,cgroup | grep /system.slice/$p.service | awk '{print $1}')
1808 ;;
1809 *)
1810 pid=$(s systemctl show --property MainPID --value $p)
1811 ;;
1812 esac
1813 echo p=$p pid=$pid
1814 if [[ ! $pid ]]; then
1815 echo failed to find pid for $p
1816 continue
1817 fi
1818 if ! ns=$(s readlink /proc/$pid/ns/net); then
1819 echo failed to find ns for $p pid=$pid
1820 continue
1821 fi
1822 if [[ $mailnn ]]; then
1823 if [[ $ns != "$mailnn" ]]; then
1824 echo "$p ns $ns != $mailnn"
1825 fi
1826 else
1827 mailnn=$ns
1828 fi
1829 done
1830
1831 }
1832
1833
1834 vpncmd() {
1835 m sudo -E env "PATH=$PATH" nsenter -t $(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*client.conf") -n "$@"
1836 }
1837
1838 vpn2f() {
1839 sudo -v
1840 vpncmd sudo -u iank env "PATH=$PATH" abrowser -no-remote -P vpn2 & r
1841 }
1842
1843 vpni() {
1844 vpncmd sudo -u iank env "PATH=$PATH" "$@"
1845 }
1846 vpnbash() {
1847 vpncmd bash
1848 }
1849
1850
1851 vpn() {
1852 if [[ -e /lib/systemd/system/openvpn-client@.service ]]; then
1853 local vpn_service=openvpn-client
1854 else
1855 local vpn_service=openvpn
1856 fi
1857
1858 [[ $1 ]] || { echo need arg; return 1; }
1859 journalctl --unit=$vpn_service@$1 -f -n0 &
1860 # sometimes the journal doesnt open until after the vpn output
1861 # has happened. hoping this fixes that.
1862 sleep 1
1863 sudo systemctl start $vpn_service@$1
1864 # sometimes the ask-password agent does not work and needs a delay.
1865 sleep .5
1866 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=779240
1867 # noticed around 8-2017 after update from around stretch release
1868 # on debian testing, even though the bug is much older.
1869 sudo systemd-tty-ask-password-agent
1870 }
1871
1872 fixu() {
1873 ls -lad /run/user/1000
1874 s chmod 700 /run/user/1000; s chown iank.iank /run/user/1000
1875 }
1876
1877 # systemctl is-enabled / status / cat says nothing, instead theres
1878 # some obscure symlink. paths copied from man systemd.unit.
1879 # possibly also usefull, but incomplete, doesnt show units not loaded in memory:
1880 # seru list-dependencies --reverse --all UNIT
1881 sysd-deps() {
1882 local f
1883 local -a dirs search
1884 ngset
1885
1886 case $1 in
1887 u)
1888 search=(
1889 ~/.config/systemd/user.control/*
1890 $XDG_RUNTIME_DIR/systemd/user.control/*
1891 $XDG_RUNTIME_DIR/systemd/transient/*
1892 $XDG_RUNTIME_DIR/systemd/generator.early/*
1893 ~/.config/systemd/user/*
1894 /etc/systemd/user/*
1895 $XDG_RUNTIME_DIR/systemd/user/*
1896 /run/systemd/user/*
1897 $XDG_RUNTIME_DIR/systemd/generator/*
1898 ~/.local/share/systemd/user/*
1899 /usr/lib/systemd/user/*
1900 $XDG_RUNTIME_DIR/systemd/generator.late/*
1901 )
1902 ;;
1903 *)
1904 search=(
1905 /etc/systemd/system.control/*
1906 /run/systemd/system.control/*
1907 /run/systemd/transient/*
1908 /run/systemd/generator.early/*
1909 /etc/systemd/system/*
1910 /etc/systemd/systemd.attached/*
1911 /run/systemd/system/*
1912 /run/systemd/systemd.attached/*
1913 /run/systemd/generator/*
1914 /lib/systemd/system/*
1915 /run/systemd/generator.late/*
1916 )
1917 ;;
1918 esac
1919 for f in "${search[@]}"; do
1920 [[ -d $f ]] || continue
1921 case $f in
1922 *.requires|*.wants)
1923 dirs+=("$f")
1924 ;;
1925 esac
1926 done
1927 # dirs is just so we write out the directory names, ls does it when there is 2 or more dirs.
1928 case ${#dirs[@]} in
1929 1)
1930 echo "${dirs[0]}:"
1931 ll "${dirs[@]}"
1932 ;;
1933 0) : ;;
1934 *)
1935 ll "${dirs[@]}"
1936 ;;
1937 esac
1938 ngreset
1939 }
1940
1941 fixvpndns() {
1942 local link istls
1943 read _ link _ istls < <(resolvectl dnsovertls tunfsf)
1944 case $istls in
1945 yes|no) : ;;
1946 *) echo fixvpndns error: unexpected istls value: $istls >&2; return 1 ;;
1947 esac
1948 s busctl call org.freedesktop.resolve1 /org/freedesktop/resolve1 org.freedesktop.resolve1.Manager SetLinkDNSOverTLS is $link no
1949 }
1950
1951 vpnoff() {
1952 [[ $1 ]] || { echo need arg; return 1; }
1953 if [[ -e /lib/systemd/system/openvpn-client@.service ]]; then
1954 local vpn_service=openvpn-client
1955 else
1956 local vpn_service=openvpn
1957 fi
1958 sudo systemctl stop $vpn_service@$1
1959 }
1960 vpnoffc() { # vpn off client
1961 ser stop openvpn-client-tr@client
1962 }
1963 vpnc() {
1964 ser start openvpn-client-tr@client
1965 }
1966
1967
1968 vspicy() { # usage: VIRSH_DOMAIN
1969 # connect to vms made with virt-install
1970 spicy -p $(sudo virsh dumpxml "$1"|grep "<graphics.*type='spice'"|\
1971 sed -r "s/.*port='([0-9]+).*/\1/")
1972 }
1973
1974 wian() {
1975 cat-new-files /m/4e/INBOX/new
1976 }
1977
1978 wtr() { curl wttr.in/boston; }
1979
1980 xevkb() { xev -event keyboard; }
1981
1982 # * misc stuff
1983
1984 vrun() {
1985 printf "running: %s\n" "$*"
1986 "$@"
1987 }
1988
1989 f=/a/f/ansible-configs/files/common/etc/fsf-workstation-bashrc.sh
1990 if [[ -e $f ]]; then
1991 # shellcheck disable=SC1090
1992 source $f
1993 fi
1994
1995 electrum() {
1996 # https://electrum.readthedocs.io/en/latest/tor.html
1997 # https://github.com/spesmilo/electrum-docs/issues/129
1998 s rsync -ptog --chown bitcoin:bitcoin ~/.Xauthority /var/lib/bitcoind/.Xauthority
1999 sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/electrum-4.2.1-x86_64.AppImage -p socks5:localhost:9050
2000 }
2001 monero() {
2002 sudo -u bitcoin DISPLAY=$DISPLAY XAUTHORITY=/var/lib/bitcoind/.Xauthority /a/opt/monero-gui-v0.17.3.2/monero-wallet-gui
2003 }
2004
2005
2006 reset-konsole() {
2007 # we also have a file in /a/c/...konsole...
2008 local f=$HOME/.config/konsolerc
2009 setini DefaultProfile profileian.profile "Desktop Entry" $f
2010 setini Favorites profileian.profile "Favorite Profiles" $f
2011 setini ShowMenuBarByDefault false KonsoleWindow $f
2012 setini TabBarPosition Top TabBar $f
2013 }
2014
2015 reset-sakura() {
2016 while read -r k v; do
2017 # shellcheck disable=SC2154
2018 setini $k $v sakura /a/c/subdir_files/.config/sakura/sakura.conf
2019 done <<'EOF'
2020 colorset1_back rgb(33,37,39)
2021 less_questions true
2022 audible_bell No
2023 visible_bell No
2024 disable_numbered_tabswitch true
2025 scroll_lines 10000000
2026 scrollbar true
2027 EOF
2028 }
2029
2030 # make a page of links found in the files $@. redirect output
2031 linkhtml() {
2032 gr -oh 'https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)' "$@" | \
2033 rev | sort -u | rev | sed 's,.*,<a href="\0">\0</a><br\>,'
2034 }
2035
2036 reset-xscreensaver() {
2037 # except for spash, i set these by setting gui options in
2038 # xscreensaver-command -demo
2039 # then finding the corresponding option in .xscreensaver
2040 # spash, i happened to notice in .xscreensaver
2041 #
2042 # dpmsOff, monitor doesnt come back on using old free software supported nvidia card
2043 cat > /home/iank/.xscreensaver <<'EOF'
2044 mode: blank
2045 dpmsEnabled: True
2046 dpmsStandby: 0:07:00
2047 dpmsSuspend: 0:08:00
2048 dpmsOff: 0:00:00
2049 timeout: 0:05:00
2050 lock: True
2051 lockTimeout: 0:06:00
2052 splash: False
2053 EOF
2054
2055 }
2056
2057
2058 # * stuff that makes sense to be at the end
2059 if [[ "$SUDOD" ]]; then
2060 # allow failure, for example if we are sudoing into a user with diffferent/lesser permissions.
2061 cd "$SUDOD" ||:
2062 unset SUDOD
2063 elif [[ -d /a ]] && [[ $PWD == "$HOME" ]] && [[ $- == *i* ]]; then
2064 cd /a
2065 fi
2066
2067
2068
2069
2070 # for mitmproxy to get a newer python.
2071 # commented until i want to use it because it
2072 # noticably slows bash startup
2073 #
2074
2075 mypyenvinit () {
2076 if [[ $EUID == 0 || ! -e ~/.pyenv/bin ]]; then
2077 echo "error: dont be root. make sure pyenv is installed"
2078 return 1
2079 fi
2080 export PATH="$HOME/.pyenv/bin:$PATH"
2081 eval "$(pyenv init -)"
2082 eval "$(pyenv virtualenv-init -)"
2083 }
2084
2085
2086 export GOPATH=$HOME/go
2087 path-add $GOPATH/bin
2088 path-add /usr/local/go/bin
2089
2090 # I have the git repo and a release. either one should work.
2091 # I have both because I was trying to solve an issue that
2092 # turned out to be unrelated.
2093 # ARDUINO_PATH=/a/opt/Arduino/build/linux/work
2094
2095 ## i should have documented this...
2096 # based on https://github.com/keyboardio/Kaleidoscope
2097 export KALEIDOSCOPE_DIR=/a/opt/Kaleidoscope
2098
2099 # They want to be added to the start, but i think
2100 # that should be avoided unless we really need it.
2101 path-add --end ~/.npm-global
2102
2103
2104 path-add --end $HOME/.cargo/bin
2105
2106 if type -P rg &>/dev/null; then
2107 # --no-messages because of annoying errors on broken symlinks
2108 rg() { command rg --no-messages -L -i -M 300 --no-ignore "$@" || return $?; }
2109 #fails if not exist. ignore
2110 complete -r rg 2>/dev/null ||:
2111 else
2112 alias rg=grr
2113 fi
2114
2115
2116
2117 # taken from default changes to bashrc and bash_profile
2118 path-add --end --ifexists $HOME/.rvm/bin
2119 # also had ruby bin dir, but moved that to environment.sh
2120 # so its included in overall env
2121
2122
2123 export BASEFILE_DIR=/a/bin/fai-basefiles
2124
2125 #export ANDROID_HOME=/a/opt/android-home
2126 # https://f-droid.org/en/docs/Installing_the_Server_and_Repo_Tools/
2127 #export USE_SDK_WRAPPER=yes
2128 #PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
2129
2130 # didnt get drush working, if I did, this seems like the
2131 # only good thing to include for it.
2132 # Include Drush completion.
2133 # if [ -f "/home/ian/.drush/drush.complete.sh" ] ; then
2134 # source /home/ian/.drush/drush.complete.sh
2135 # fi
2136
2137
2138 # best practice
2139 unset IFS
2140
2141 # https://wiki.archlinux.org/index.php/Xinitrc#Autostart_X_at_login
2142 # i added an extra condition as gentoo xorg guide says depending on
2143 # $DISPLAY is fragile.
2144 if [[ ! $DISPLAY && $XDG_VTNR == 1 ]] && shopt -q login_shell && isarch; then
2145 exec startx
2146 fi
2147
2148
2149 # ensure no bad programs appending to this file will have an affect
2150 return 0