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