bff0eb755462d8ee91cd3f31cda1ac340e84db73
[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
16 # pip3 --user things go here:
17 path-add --end ~/.local/bin
18 path-add --ifexists --end /a/work/libremanage
19 path-add --ifexists --end /a/opt/adt-bundle*/tools /a/opt/adt-bundle*/platform-tools
20 path-add --ifexists --end /a/opt/scancode-toolkit-3.0.2
21
22 export WCDHOME=/a
23
24
25 # * include files
26
27 # generated instead of dynamic for the benefit of shellcheck
28 #for x in /a/bin/distro-functions/src/* /a/bin/!(githtml)/*-function?(s); do echo source $x ; done
29 source /a/bin/distro-functions/src/identify-distros
30 source /a/bin/distro-functions/src/package-manager-abstractions
31 source /a/bin/log-quiet/logq-function
32 source /a/bin/small-misc-bash/psg-function
33 # for x in /a/bin/bash_unpublished/source-!(.#*); do echo source $x; done
34 source /a/bin/bash_unpublished/source-semi-priv
35 source /a/bin/bash_unpublished/source-state
36
37 source /a/bin/log-quiet/logq-function
38
39
40
41 # * functions
42
43
44
45 # todo, update this
46 complete -F _longopt la lower low rlt rld rl lld ts ll dircp ex fcp fct fpst gr
47
48
49 anki() {
50 if which anki &>/dev/null; then
51 command anki
52 else
53 schroot -c anki -- anki
54 fi
55 }
56
57 ap() {
58 # pushd in case current directory has an ansible.cfg file
59 pushd /a/xans >/dev/null
60 ansible-playbook -v -l ${1:- $(hostname -f)} site.yml
61 popd >/dev/null
62 }
63 aw() {
64 pushd /a/work/ansible-configs >/dev/null
65 time ansible-playbook -v -i inventory adhoc.yml "$@"
66 popd >/dev/null
67 }
68 ad() {
69 pushd /a/bin/distro-setup/a >/dev/null
70 ansible-playbook site.yml
71 popd >/dev/null
72 }
73
74 astudio() {
75 # googling android emulator libGL error: failed to load driver: r600
76 # lead to http://stackoverflow.com/a/36625175/14456
77 export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1
78 /a/opt/android-studio/bin/studio.sh "$@" &r;
79 }
80
81
82 bbk() { # btrbk wrapper
83 c /
84 local active=true
85 systemctl is-active btrbk.timer || active=false
86 if $active; then
87 ser disable btrbk.timer
88 fi
89 if systemctl is-active btrbk.service; then
90 $active && ser enable btrbk.timer
91 echo "cron btrbk is already running"
92 return 1
93 fi
94 # run latest
95 install-my-scripts
96 btrbk-run "$@" | pee cat "systemd-cat -t btrbk-run"
97 $active && ser enable btrbk.timer
98 }
99
100 bfg() { java -jar /a/opt/bfg-1.12.14.jar "$@"; }
101
102 bigclock() {
103 xclock -digital -update 1 -face 'arial black-80:bold'
104 }
105
106 bpull() {
107 [[ $1 ]] || return 1
108 c /
109 # run latest
110 install-my-scripts
111 switch-mail-host $1 $HOSTNAME | pee cat "systemd-cat -t switch-mail-host"
112 }
113 bpush() {
114 [[ $1 ]] || return 1
115 c /
116 # run latest
117 install-my-scripts
118 switch-mail-host $HOSTNAME $1 | pee cat "systemd-cat -t switch-mail-host"
119 }
120 lipush() {
121 rsync $@ --delete-excluded -ahviSAXPH --specials --devices --delete --relative \
122 --exclude-from=/p/c/li-rsync-excludes /a/bin /a/exe /a/h /a/c /p/c/machine_specific/li /a/opt/{emacs,emacs-debianstable,mu} root@li:/
123 }
124 lipushnoe() {
125 rsync $@ --delete-excluded -ahviSAXPH --specials --devices --delete --relative \
126 --exclude-from=/p/c/li-rsync-excludes /a/bin /a/exe /a/h /a/c /p/c/machine_specific/li root@li:/
127 }
128
129
130 #### begin bitcoin related things
131 btc() {
132 local f=/etc/bitcoin/bitcoin.conf
133 # importprivkey will timeout if using the default of 15 mins.
134 # upped it to 1 hour.
135 bitcoin-cli -rpcclienttimeout=60000 -$(s grep rpcuser= $f) -$(s grep rpcpassword= $f) "$@"
136 }
137 btcusd() { # $1 btc in usd
138 local price
139 price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
140 printf "$%s\n" "$price"
141 if [[ $1 ]]; then
142 printf "$%.2f\n" "$(echo "scale=4; $price * $1"| bc -l)"
143 fi
144 }
145 usdbtc() { # $1 usd in btc
146 local price
147 price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
148 printf "$%s\n" "$price"
149 if [[ $1 ]]; then
150 # 100 mil satoshi / btc. 8 digits after the 1.
151 printf "%.8f btc\n" "$(echo "scale=10; $1 / $price "| bc -l)"
152 fi
153 }
154 satoshi() { # $1 satoshi in usd
155 local price
156 price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
157 price=$(echo "scale=10; $price * 0.00000001"| bc -l)
158 printf "$%f\n" "$price"
159 if [[ $1 ]]; then
160 printf "$%.2f\n" "$(echo "scale=10; $price * $1"| bc -l)"
161 fi
162 }
163 #### end bitcoin related things
164
165
166
167 cbfstool () { /a/opt/coreboot/build/cbfstool "$@"; }
168
169
170 cgpl()
171 {
172 if (($#)); then
173 cp /a/bin/data/COPYING "$@"
174 else
175 cp /a/bin/data/COPYING .
176 fi
177 }
178
179 capache()
180 {
181 if (($#)); then
182 cp /a/bin/data/LICENSE "$@"
183 else
184 cp /a/bin/data/LICENSE .
185 fi
186 }
187
188 chrome() {
189 if type -p chromium &>/dev/null; then
190 cmd=chromium
191 else
192 cd
193 cmd="schroot -c stretch chromium"
194 CHROMIUM_FLAGS='--enable-remote-extensions' $cmd &r
195 fi
196 }
197
198
199 dat() { # do all tee, for more complex scripts
200 tee >(ssh frodo bash -l) >(bash -l) >(ssh x2 bash -l) >(ssh tp bash -l)
201 }
202 da() { # do all
203 local host
204 "$@"
205 for host in x2 tp kd; do
206 ssh $host $(printf "")
207 done
208 }
209
210
211 debian_pick_mirror () {
212 # netselect-apt finds a fast mirror.
213 # but we need to replace the mirrors ourselves,
214 # because it doesnt do that. best it can do is
215 # output a basic sources file
216 # here we get the server it found, get the main server we use
217 # then substitute all instances of one for the other in the sources file
218 # and backup original to /etc/apt/sources.list-original.
219 # this is idempotent. the only way to identify debian sources is to
220 # note the original server, so we put it in a comment so we can
221 # identify it later.
222 local file
223 file=$(mktemp -d)/f # safe way to get file name without creating one
224 sudo netselect-apt -o "$file" || return 1
225 url=$(grep ^\\w $file | head -n1 | awk '{print $2}')
226 sudo cp -f /etc/apt/sources.list /etc/apt/sources.list-original
227 sudo sed -ri "/http.us.debian.org/ s@( *[^ #]+ +)[^ ]+([^#]+).*@\1$url\2# http.us.debian.org@" /etc/apt/sources.list
228 sudo apt-get update
229 }
230
231 dup() {
232 local ran_d
233 ran_d=false
234 case $PS1 in
235 *DISTRO-BEGIN*)
236 /b/ds/distro-begin
237 ran_d=true
238 ;;&
239 *DISTRO-END*)
240 /b/ds/distro-end
241 ran_d=true
242 ;;&
243 *CONFLINK*)
244 if ! $ran_d; then
245 conflink
246 fi
247 ;;
248 esac
249 }
250
251 envload() { # load environment from a previous: export > file
252 local file=${1:-$HOME/.${USER}_env}
253 eval "$(export | sed 's/^declare -x/export -n/')"
254 while IFS= read -r line; do
255 # declare -x makes variables local to a function
256 eval ${line/#declare -x/export}
257 done < "$file"
258 }
259
260
261 # one that comes with distros is too old for newer devices
262 fastboot() {
263 /a/opt/android-platform-tools/fastboot "$@";
264 }
265
266 kdecd() { /usr/lib/x86_64-linux-gnu/libexec/kdeconnectd; }
267
268 # List of apps to install/update
269 # Create from existing manually installed apps by doing
270 # fdroidcl update
271 # fdroidcl search -i, then manually removing
272 # automatically installed/preinstalled apps
273
274 #
275 # # my attempt at recovering from boot loop:
276 # # in that case, boot to recovery (volume up, home button, power, let go of power after samsun logo)
277 # # then
278 # mount /dev/block/mmcblk0p12 /data
279 # cd /data
280 # find -iname '*appname*'
281 # rm -rf FOUND_DIRS
282 # usually good enough to just rm -rf /data/app/APPNAME
283 #
284 # currently broken:
285 # # causes replicant to crash
286 # org.quantumbadger.redreader
287 # org.kde.kdeconnect_tp
288
289 # not broke, but wont work without gps
290 #com.zoffcc.applications.zanavi
291 # not broke, but not using atm
292 #com.nutomic.syncthingandroid
293 # # doesn\'t work on replicant
294 #net.sourceforge.opencamera
295 #
296 fdroid_pkgs=(
297 de.marmaro.krt.ffupdater
298 me.ccrama.redditslide
299 org.fedorahosted.freeotp
300 at.bitfire.davdroid
301 com.alaskalinuxuser.justnotes
302 com.artifex.mupdf.viewer.app
303 com.danielkim.soundrecorder
304 com.fsck.k9
305 com.ghostsq.commander
306 com.ichi2.anki
307 com.jmstudios.redmoon
308 com.jmstudios.chibe
309 org.kde.kdeconnect_tp
310 com.notecryptpro
311 com.termux
312 cz.martykan.forecastie
313 de.danoeh.antennapod
314 de.blinkt.openvpn
315 de.marmaro.krt.ffupdater
316 eu.siacs.conversations
317 free.rm.skytube.oss
318 im.vector.alpha # riot
319 info.papdt.blackblub
320 me.tripsit.tripmobile
321 net.gaast.giggity
322 net.minetest.minetest
323 net.osmand.plus
324 org.isoron.uhabits
325 org.linphone
326 org.gnu.icecat
327 org.smssecure.smssecure
328 org.yaaic
329 sh.ftp.rocketninelabs.meditationassistant.opensource
330 )
331 # https://forum.xda-developers.com/android/software-hacking/wip-selinux-capable-superuser-t3216394
332 # for maru,
333 #me.phh.superuser
334
335 fdup() {
336 local -A installed updated
337 local p
338 fdroidcl update
339 if fdroidcl search -u | grep ^org.fdroid.fdroid; then
340 fdroidcl install org.fdroid.fdroid
341 sleep 5
342 fdroidcl update
343 fi
344 for p in $(fdroidcl search -i| grep -o "^\S\+"); do
345 installed[$p]=true
346 done
347 for p in $(fdroidcl search -u| grep -o "^\S\+"); do
348 updated[$p]=false
349 done
350 for p in ${fdroid_pkgs[@]}; do
351 if ! ${installed[$p]:-false}; then
352 fdroidcl install $p
353 # sleeps are just me being paranoid since replicant has a history of crashing when certain apps are installed
354 sleep 5
355 fi
356 done
357 for p in ${!installed[@]}; do
358 if ! ${updated[$p]:-true}; then
359 fdroidcl install $p
360 sleep 5
361 fi
362 done
363 }
364
365 firefox-default-profile() {
366 key=Default value=1 section=$1
367 file=/p/c/subdir_files/.mozilla/firefox/profiles.ini
368 sed -ri "/^ *$key/d" "$file"
369 sed -ri "/ *\[$section\]/,/^ *\[[^]]+\]/{/^\s*$key[[:space:]=]/d};/ *\[$section\]/a $key=$value" "$file"
370 }
371 fdhome() { #firefox default home profile
372 firefox-default-profile Profile0
373 }
374
375 fdwork() {
376 firefox-default-profile Profile4
377 }
378
379 ff() {
380 if type -P firefox &>/dev/null; then
381 firefox "$@"
382 else
383 iceweasel "$@"
384 fi
385 }
386
387
388
389 fn() {
390 firefox -P alt "$@" >/dev/null 2>&1
391 }
392
393
394 fsdiff () {
395 local missing=false
396 local dname="${PWD##*/}"
397 local m="/a/tmp/$dname-missing"
398 local d="/a/tmp/$dname-diff"
399 [[ -e $d ]] && rm "$d"
400 [[ -e $m ]] && rm "$m"
401 local msize=0
402 local fsfile
403 while read -r line; do
404 fsfile="$1${line#.}"
405 if [[ -e "$fsfile" ]]; then
406 md5diff "$line" "$fsfile" && tee -a "/a/tmp/$dname-diff" <<< "$fsfile $line"
407 else
408 missing=true
409 echo "$line" >> "$m"
410 msize=$((msize + 1))
411 fi
412 done < <(find . -type f )
413 if $missing; then
414 echo "$m"
415 (( msize <= 100 )) && cat $m
416 fi
417 }
418 fsdiff-test() {
419 # expected output, with different tmp dirs
420 # /tmp/tmp.HDPbwMqdC9/c/d ./c/d
421 # /a/tmp/tmp.qLDkYxBYPM-missing
422 # ./b
423 cd $(mktemp -d)
424 echo ok > a
425 echo nok > b
426 mkdir c
427 echo ok > c/d
428 local x
429 x=$(mktemp -d)
430 mkdir $x/c
431 echo different > $x/c/d
432 echo ok > $x/a
433 fsdiff $x
434 }
435 rename-test() {
436 # test whether missing files were renamed, generally for use with fsdiff
437 # $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir
438 # echos non-renamed files
439 local x y found
440 unset sums
441 for x in "$2"/*; do
442 { sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null
443 done
444 while read -r line; do
445 { missing_sum=$(md5sum < "$line") ; } 2>/dev/null
446 renamed=false
447 for x in "${sums[@]}"; do
448 if [[ $missing_sum == "$x" ]]; then
449 renamed=true
450 break
451 fi
452 done
453 $renamed || echo "$line"
454 done < "$1"
455 return 0
456 }
457
458 feh() {
459 # F = fullscren, z = random, Z = auto zoom
460 command feh -FzZ "$@"
461 }
462
463
464
465 fw() {
466 firefox -P default "$@" >/dev/null 2>&1
467 }
468
469
470 gitian() {
471 git config user.email ian@iankelling.org
472 }
473
474
475 # at least in flidas, things rely on gpg being gpg1
476 gpg() {
477 command gpg2 "$@"
478 }
479
480 gse() {
481 local email=ian@iankelling.org
482 if readlink ~/.mu | grep fsf &>/dev/null; then
483 email=iank@fsf.org
484 fi
485 git send-email --notes "--envelope-sender=<$email>" \
486 --suppress-cc=self "$@"
487 }
488
489
490 hstatus() {
491 # do git status on published repos.
492 c /a/bin/githtml
493 for x in *; do
494 cd $(readlink -f $x)/..
495 status=$(i status -s) || pwd
496 if [[ $status ]]; then
497 hr
498 echo $x
499 printf "%s\n" "$status"
500 fi
501 cd /a/bin/githtml
502 done
503 }
504
505
506 idea() {
507 /a/opt/idea-IC-163.7743.44/bin/idea.sh "$@" &r
508 }
509
510 o() {
511 if type gvfs-open &> /dev/null ; then
512 gvfs-open "$@"
513 else
514 xdg-open "$@"
515 fi
516 # another alternative is run-mailcap
517 }
518
519 jfilter() {
520 grep -Evi -e "^(\S+\s+){4}(sudo|sshd|cron)\[\S*:" \
521 -e "^(\S+\s+){4}systemd\[\S*: (starting|started) (btrfsmaintstop|dynamicipupdate|spamd dns bug fix cronjob|rss2email)\.*$"
522 }
523 jtail() {
524 journalctl -n 10000 -f "$@" | jfilter
525 }
526 jr() { journalctl "$@" | jfilter | less ; }
527 jrf() { journalctl -f "$@" | jfilter; }
528
529
530 kff() { # keyboardio firmware flash
531 pushd /a/bin/distro-setup/Arduino/Model01-Firmware
532 yes $'\n' | make flash
533 popd
534 }
535
536
537
538 lom() {
539 local l base
540 if [[ $1 == /* ]]; then
541 base=${1##*/}
542 if mountpoint /mnt/$base; then
543 return 0
544 fi
545 l=$(sudo losetup -f)
546 sudo losetup $l $1
547 if ! sudo cryptsetup luksOpen $l $base; then
548 sudo losetup -d $l
549 return 1
550 fi
551 sudo mkdir -p /mnt/$base
552 sudo mount /dev/mapper/$base /mnt/$base
553 sudo chown $USER:$USER /mnt/$base
554 else
555 base=$1
556 sudo umount /mnt/$base
557 l=$(sudo cryptsetup status /dev/mapper/$base|sed -rn 's/^\s*device:\s*(.*)/\1/p')
558 sudo cryptsetup luksClose /dev/mapper/$base || return 1
559 sudo losetup -d $l
560 fi
561 }
562
563
564 mbenable() {
565 local mb=$1
566 dst=/m/4e/$mb
567 src=/m/md/$mb
568 set -x
569 [[ -e $src ]] || { set +x; return 1; }
570 mv -T $src $dst || { set +x; return 1; }
571 ln -s -T $dst $src
572 /a/exe/lnf /m/.mu ~
573 mu index --maildir=/m/4e
574 set +x
575 }
576 mbdisable() {
577 local mb=$1
578 dst=/m/md/$mb
579 src=/m/4e/$mb
580 set -x
581 [[ -e $src ]] || { set +x; return 1; }
582 if [[ -L $dst ]]; then rm $dst; fi
583 mv -T $src $dst
584 set +x
585 }
586
587
588 mdt() {
589 markdown "$1" >/tmp/mdtest.html
590 firefox /tmp/mdtest.html
591 }
592
593
594
595 mo() { xset dpms force off; } # monitor off
596
597 net-dev-info() {
598 e "lspci -nnk|gr -iA2 net"
599 lspci -nnk|gr -iA2 net
600 hr
601 e "s lshw -C network"
602 hr
603 s lshw -C network
604
605 }
606
607 nk() {
608 ser stop NetworkManager
609 ser stop dnsmasq
610 s resolvconf -d NetworkManager
611 ser start dnsmasq
612 s ifup br0
613 }
614 ngo() {
615 s ifdown br0
616 ser start NetworkManager
617 sleep 4
618 s nmtui-connect
619 }
620
621 otp() {
622 oathtool --totp -b "$@" | xclip -selection clipboard
623 }
624
625
626 pakaraoke() {
627 # from http://askubuntu.com/questions/456021/remove-vocals-from-mp3-and-get-only-instrumentals
628 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
629 }
630
631 pfind() { #find *$1* in $PATH
632 [[ $# != 1 ]] && { echo requires 1 argument; return 1; }
633 local pathArray
634 IFS=: pathArray=($PATH); unset IFS
635 find "${pathArray[@]}" -iname "*$1*"
636 }
637
638 pick-trash() {
639 # trash-restore lists everything that has been trashed at or below CWD
640 # This picks out files just in CWD, not subdirectories,
641 # which also match grep $1, usually use $1 for a time string
642 # which you get from running restore-trash once first
643 local name x ask
644 local nth=1
645 # last condition is to not ask again for ones we skipped
646 while name="$( echo | restore-trash | gr "$PWD/[^/]\+$" | gr "$1" )" \
647 && [[ $name ]] && (( $(wc -l <<<"$name") >= nth )); do
648 name="$(echo "$name" | head -n $nth | tail -n 1 )"
649 read -r -p "$name [Y/n] " ask
650 if [[ ! $ask || $ask == [Yy] ]]; then
651 x=$( echo "$name" | gr -o "^\s*[0-9]*" )
652 echo $x | restore-trash > /dev/null
653 elif [[ $ask == [Nn] ]]; then
654 nth=$((nth+1))
655 else
656 return
657 fi
658 done
659 }
660
661
662 pub() {
663 rld /a/h/_site/ li:/var/www/iankelling.org/html
664 }
665
666
667 pumpa() {
668 # fixes the menu bar in xmonad. this won\'t be needed when xmonad
669 # packages catches up on some changes in future (this is written in
670 # 4/2017)
671 #
672 # geekosaur: so youll want to upgrade to xmonad 0.13 or else use a
673 # locally modified XMonad.Hooks.ManageDocks that doesnt set the
674 # work area; turns out it\'s impossible to set correctly if you are
675 # not a fully EWMH compliant desktop environment
676 #
677 # geekosaur: chrome shows one failure mode, qt/kde another, other
678 # gtk apps a third, ... I came up with a setting that works for me
679 # locally but apparently doesnt work for others, so we joined the
680 # other tiling window managers in giving up on setting it at all
681 #
682 xprop -root -remove _NET_WORKAREA
683 command pumpa &r
684 }
685
686 # reviewboard, used at my old job
687 #rbpipe() { rbt post -o --diff-filename=- "$@"; }
688 #rbp() { rbt post -o "$@"; }
689
690 rebr() {
691 s ifdown br0
692 s ifup br0
693 }
694
695 resolvcat() {
696 local f
697 f=/etc/resolv.conf
698 echo $f:; ccat $f
699 hr; echo dnsmasq is $(systemctl is-active dnsmasq)
700 f=/var/run/dnsmasq/resolv.conf
701 hr; echo $f:; ccat $f
702 f=/etc/dnsmasq-servers.conf
703 hr; echo $f:; ccat $f
704 }
705
706 # only run on MAIL_HOST. simpler to keep this on one system.
707 r2eadd() { # usage: name url
708 # initial setup of rss2email:
709 # r2e new r2e@iankelling.org
710 # that initializes files, and sets default email.
711 # symlink to the config doesnt work, so I copied it to /p/c
712 # and then use cli option to specify explicit path.
713 # Only option changed from default config is to set
714 # force-from = True
715 #
716 # or else for a few feeds, the from address is set by the feed, and
717 # if I fail delivery, then I send a bounce message to that from
718 # address, which makes me be a spammer.
719
720 r2e add $1 "$2" $1@r2e.iankelling.org
721 # get up to date and dont send old entries now:
722 r2e run --no-send $1
723 }
724 r2e() { command r2e -d /p/c/rss2email.json -c /p/c/rss2email.cfg "$@"; }
725
726 rspicy() { # usage: HOST DOMAIN
727 # connect to spice vm remote host. use vspicy for local host
728 local port
729 # shellcheck disable=SC2087
730 port=$(ssh $1<<EOF
731 sudo virsh dumpxml $2|grep "<graphics.*type='spice'" | \
732 sed -rn "s/.*port='([0-9]+).*/\1/p"
733 EOF
734 )
735 if [[ $port ]]; then
736 spicy -h $1 -p $port
737 else
738 echo "error: no port found. check that the domain is running."
739 fi
740 }
741
742
743 scssl() {
744 # s gem install scss-lint
745 pushd /a/opt/thoughtbot-guides
746 git pull --stat
747 popd
748 scss-lint -c /a/opt/thoughtbot-guides/style/sass/.scss-lint.yml "$@"
749 }
750
751 skaraoke() {
752 local tmp out
753 out=${2:-${1%.*}.sh}
754 tmp=$(mktemp -d)
755 script -t -c "mpv --no-config --no-resume-playback --no-terminal --no-audio-display '$1'" $tmp/typescript 2>$tmp/timing
756 # todo, the current sleep seems pretty good, but it
757 # would be nice to have an empirical measurement, or
758 # some better wait to sync up.
759 #
760 # note: --loop-file=no prevents it from hanging if you have that
761 # set to inf the mpv config.
762 # --loop=no prevents it from exit code 3 due to stdin if you
763 # had it set to inf in mpv config.
764 #
765 # args go to mpv, for example --volume=80, 50%
766 cat >$out <<EOFOUTER
767 #!/bin/bash
768 trap "trap - TERM && kill 0" INT TERM ERR; set -e
769 ( sleep .2; scriptreplay <( cat <<'EOF'
770 $(cat $tmp/timing)
771 EOF
772 ) <( cat <<'EOF'
773 $(cat $tmp/typescript)
774 EOF
775 ))&
776 base64 -d - <<'EOF'| mpv --loop=no --loop-file=no --no-terminal --no-audio-display "\$@" -
777 $(base64 "$1")
778 EOF
779 kill 0
780 EOFOUTER
781 rm -r $tmp
782 chmod +x $out
783 }
784
785 smeld() { # ssh meld usage host1 host2 file
786 meld <(ssh $1 cat $3) <(ssh $2 cat $3)
787 }
788
789 spd() {
790 PATH=/usr/local/spdhackfix:$PATH command spd "$@"
791 }
792
793 spend() {
794 s systemctl suspend
795 }
796
797 # ssh, copy my universal config over if needed.
798 sl() {
799 # inspired from https://github.com/Russell91/sshrc
800
801
802 local args info_date info_t type now tmp old sshinfo
803 declare -a args tmpa
804 now=$(date +%s)
805
806 # ssh [-1246Antivivisectionist] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
807 # [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-L address]
808 # [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port] [-Q query_option]
809 # [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] [user@]hostname
810 # [command]
811
812 while [[ $1 ]]; do
813 case "$1" in
814 -[1246AaCfGgKkMNnqsTtVvXxYy])
815 args+=("$1"); shift
816 ;;
817 -[bcDEeFIiLlmOopQRSWw])
818 # -oOption etc is valid
819 if (( ${#1} >= 3 )); then
820 args+=("$1"); shift
821 else
822 args+=("$1" "$2"); shift 2
823 fi
824 ;;
825 *)
826 break
827 ;;
828 esac
829 done
830 remote="$1"; shift
831 old=false
832 tmpa=(/p/sshinfo/???????????"$remote")
833 sshinfo=${tmpa[0]}
834 if [[ -e $sshinfo ]]; then
835 tmp=${sshinfo[0]##*/}
836 info_date=${tmp::11}
837 type=${info_date: -1}
838 info_date=${info_date::10}
839 info_sec=$(date -d @$info_date +%s)
840 # debug
841 #e $(( $(stat -c%Y /b/ds/brc) - $(date -d @$info_date +%s) ))
842 if (( $(stat -c%Y /b/ds/brc) > info_sec || $(stat -c%Y /b/ds/.bashrc) > info_sec )); then
843 old=true
844 fi
845 else
846 # use this weird yes thing to ensure we know ssh succeeded
847 tmp=$(command ssh "${args[@]}" "$remote" "if test -e /p/sshinfo; then echo yes; fi") || return
848 if [[ $tmp == yes ]]; then
849 type=a
850 else
851 type=b
852 old=true
853 fi
854 fi
855 if [[ $type == b ]]; then
856 if $old; then
857 RSYNC_RSH="ssh ${args[*]}" rsync -rptL /b/ds/.iank "$remote":
858 rm -f $sshinfo
859 sshinfo=/p/sshinfo/$now$type"$remote"
860 touch $sshinfo
861 chmod 666 $sshinfo
862 fi
863 if (( ${#@} )); then
864
865 # Theres a couple ways to do this. im not sure whats best,
866 # but relying on bash 4.4+ escape quoting seems most reliable.
867
868 command ssh -t "${args[@]}" "$remote" "INPUTRC=.iank/.inputrc bash --rcfile .iank/.bashrc -c ${@@Q}"
869 # this way is bad
870 # command ssh -t "${args[@]}" "$remote" "printf \"%s; exit\" \"$*\" >.iank/brc2
871 #INPUTRC=.iank/.inputrc bash --rcfile .iank/.bashrc"
872
873 else
874 command ssh -t "${args[@]}" "$remote" "INPUTRC=.iank/.inputrc bash --rcfile .iank/.bashrc"
875 fi
876 else
877 BASH_LOGIN_SHELL=true command ssh "$remote" "$@"
878 fi
879 }
880 sss() { # ssh solo
881 ssh -oControlMaster=no -oControlPath=/ "$@"
882 }
883 # kill off old shared socket then ssh
884 ssk() {
885 local -a opts=()
886 while [[ $1 == -* ]]; do
887 opts+=("$1")
888 shift
889 done
890 m pkill -f "^ssh: /tmp/ssh_mux_${USER}_${1#*@}_22_"
891 m ssh "${opts[@]}" "$@"
892 }
893 # plain limited ssh
894 ssh() {
895 BASH_LOGIN_SHELL=true command ssh "$@"
896 }
897
898
899 # mail related
900 testmail() {
901 declare -gi _seq; _seq+=1
902 echo "test body" | m mail -s "test mail from $HOSTNAME, $_seq" "${@:-root@localhost}"
903 # for testing to send from an external address, you can do for example
904 # -fian@iank.bid -aFrom:ian@iank.bid web-6fnbs@mail-tester.com
905 # note in exim, you can retry a deferred message
906 # s exim -M MSG_ID
907 # MSG_ID is in /var/log/exim4/mainlog, looks like 1ccdnD-0001nh-EN
908 }
909
910 # to test sieve, use below command. for fsf mail, see offlineimap-sync script
911 # make modifications, then copy to live file, use -eW to actually modify mailbox
912 #
913 # Another option is to use sieve-test SCRIPT MAIL_FILE. note,
914 # sieve-test doesnt know about envelopes, Im not sure if sieve-filter does.
915
916 # sieve with output filter. arg is mailbox, like INBOX.
917 # This depends on dovecot conf, notably mail_location in /etc/dovecot/conf.d/10-mail.conf
918
919 _dosieve() {
920 sieve-filter "$@" 2> >(head; tail) >/tmp/testsieve.log && sed -rn '/^Performed actions:/,/^[^ ]/{/^ /p}' /tmp/testsieve.log | sort | uniq -c
921 }
922
923 # always run this first, edit the test files, then run the following
924 testsieve() {
925 _dosieve ~/sieve/maintest.sieve ${1:-INBOX} delete
926 }
927 runsieve() {
928 c ~/sieve; cp personal{test,}.sieve; cp lists{test,}.sieve; cp personalend{test,}.sieve
929 _dosieve ~/sieve/main.sieve -eW ${1:-INBOX} delete
930 }
931
932 # mail related
933 testexim() {
934 # testmail above calls sendmail, which is a link to exim/postfix.
935 # its docs dont say a way of adding an argument
936 # to sendmail to turn on debug output. We could make a wrapper, but
937 # that is a pain. Exim debug args are documented here:
938 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
939 #
940 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-building_and_installing_exim.html
941 # note, for exim daemon, you can turn on debug options by
942 # adding -d, etc to COMMONOPTIONS in
943 # /etc/default/exim4
944 #
945 # to specify recipients other than those in to, cc, bcc, you can use the cli args, eg:
946 # exim -i 'test@zroe.org, t2@zroe.org' <<'EOF'
947 #
948 #
949 exim -d -t <<'EOF'
950 From: i@dmarctest.b8.nz
951 To: mailman@dev.fsf.org
952 Subject: test2
953 Reply-to: rtest@iankelling.org
954
955 This is a test message.
956 EOF
957 }
958
959 # toggle keyboard
960 tk() {
961 # based on
962 # https://askubuntu.com/questions/160945/is-there-a-way-to-disable-a-laptops-internal-keyboard
963 id=$(xinput --list --id-only 'AT Translated Set 2 keyboard')
964 if xinput list | grep -F '∼ AT Translated Set 2 keyboard' &>/dev/null; then
965 echo enabling keyboard
966 # find the first slave keyboard number, they are all the same in my output.
967 # if they werent, worst case we would need to save the slave number somewhere
968 # when it got disabled.
969 slave=$(xinput list | sed -n 's/.*slave \+keyboard (\([0-9]*\)).*/\1/p' | head -n1)
970 xinput reattach $id $slave
971 else
972 xinput float $id
973 fi
974 }
975
976 tm() {
977 # timer in minutes
978 # --no-config
979 (sleep $(calc "$* * 60") && mpv --no-config --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
980 }
981
982 trg() { transmission-remote-gtk&r; }
983 trc() {
984 # example, set global upload limit to 100 kilobytes:
985 # trc -u 100
986 TR_AUTH=":$(jq -r .profiles[0].password ~/.config/transmission-remote-gtk/config.json)" transmission-remote transmission.lan -ne "$@"
987 }
988
989
990 tu() {
991 local s dir
992 dir="$(dirname "$1")"
993 if [[ -e $1 && ! -w $1 || ! -w $(dirname "$1") ]]; then
994 s=s;
995 fi
996 # full path for using in some initial setup steps
997 $s /a/exe/teeu "$@"
998 }
999
1000 vpncmd() {
1001 #m s nsenter -t $(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*pia.conf") -n -m "$@"
1002 m s nsenter -t $(pgrep -f "/usr/sbin/openvpn .* --config /etc/openvpn/.*client.conf") -n -m "$@"
1003 }
1004 vpnf() {
1005 vpncmd gksudo -u iank "firefox -no-remote -P vpn" &r
1006 }
1007 vpni() {
1008 vpncmd gksudo -u iank "$*"
1009 }
1010 vpnbash() {
1011 vpncmd bash
1012 }
1013
1014
1015 vpn() {
1016 if [[ -e /lib/systemd/system/openvpn-client@.service ]]; then
1017 local vpn_service=openvpn-client
1018 else
1019 local vpn_service=openvpn
1020 fi
1021
1022 [[ $1 ]] || { echo need arg; return 1; }
1023 journalctl --unit=$vpn_service@$1 -f -n0 &
1024 s systemctl start $vpn_service@$1
1025 # sometimes the ask-password agent does not work and needs a delay.
1026 sleep .5
1027 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=779240
1028 # noticed around 8-2017 after update from around stretch release
1029 # on debian testing, even though the bug is much older.
1030 s systemd-tty-ask-password-agent
1031 }
1032
1033 vpnoff() {
1034 [[ $1 ]] || { echo need arg; return 1; }
1035 if [[ -e /lib/systemd/system/openvpn-client@.service ]]; then
1036 local vpn_service=openvpn-client
1037 else
1038 local vpn_service=openvpn
1039 fi
1040 s systemctl stop $vpn_service@$1
1041 }
1042
1043
1044
1045
1046 vspicy() { # usage: VIRSH_DOMAIN
1047 # connect to vms made with virt-install
1048 spicy -p $(sudo virsh dumpxml "$1"|grep "<graphics.*type='spice'"|\
1049 sed -r "s/.*port='([0-9]+).*/\1/")
1050 }
1051
1052 wian() {
1053 cat-new-files /m/4e/INBOX/new
1054 }
1055
1056 wtr() { curl wttr.in/boston; }
1057
1058 xevkb() { xev -event keyboard; }
1059
1060 # * misc stuff
1061
1062 # from curl cheat.sh/:bash_completion
1063 _cheatsh_complete_curl()
1064 {
1065 local cur prev opts
1066 _get_comp_words_by_ref -n : cur
1067
1068 COMPREPLY=()
1069 #cur="${COMP_WORDS[COMP_CWORD]}"
1070 prev="${COMP_WORDS[COMP_CWORD-1]}"
1071 opts="$(curl -s cheat.sh/:list | sed s@^@cheat.sh/@)"
1072
1073 if [[ ${cur} == cheat.sh/* ]] ; then
1074 COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
1075 __ltrim_colon_completions "$cur"
1076 return 0
1077 fi
1078 }
1079 complete -F _cheatsh_complete_curl curl
1080
1081
1082
1083
1084 reset-konsole() {
1085 # we also have a file in /a/c/...konsole...
1086 local f=$HOME/.config/konsolerc
1087 setini DefaultProfile profileian.profile "Desktop Entry" $f
1088 setini Favorites profileian.profile "Favorite Profiles" $f
1089 setini ShowMenuBarByDefault false KonsoleWindow $f
1090 setini TabBarPosition Top TabBar $f
1091 }
1092
1093 reset-sakura() {
1094 while -r read k v; do
1095 # shellcheck disable=SC2154
1096 setini $k $v sakura /a/c/subdir_files/.config/sakura/sakura.conf
1097 done <<'EOF'
1098 colorset1_back rgb(33,37,39
1099 less_questions true
1100 audible_bell No
1101 visible_bell No
1102 disable_numbered_tabswitch true
1103 scroll_lines 10000000
1104 scrollbar true
1105 EOF
1106 }
1107
1108 reset-xscreensaver() {
1109 # except for spash, i set these by setting gui options in
1110 # xscreensaver-command -demo
1111 # then finding the corresponding option in .xscreensaver
1112 # spash, i happened to notice in .xscreensaver
1113 #
1114 # dpmsOff, monitor doesnt come back on using old free software supported nvidia card
1115 cat > /home/iank/.xscreensaver <<'EOF'
1116 mode: blank
1117 dpmsEnabled: True
1118 dpmsStandby: 0:02:00
1119 dpmsSuspend: 0:03:00
1120 dpmsOff: 0:00:00
1121 timeout: 0:02:00
1122 lock: True
1123 lockTimeout: 0:03:00
1124 splash: False
1125 EOF
1126
1127 }
1128
1129
1130 # * stuff that makes sense to be at the end
1131 if [[ "$SUDOD" ]]; then
1132 cd "$SUDOD"
1133 unset SUDOD
1134 elif [[ -d /a ]] && [[ $PWD == "$HOME" ]] && [[ $- == *i* ]]; then
1135 cd /a
1136 fi
1137
1138
1139 # best practice
1140 unset IFS
1141
1142
1143 # for mitmproxy to get a newer python.
1144 # commented until i want to use it because it
1145 # noticably slows bash startup
1146 #
1147
1148 mypyenvinit () {
1149 if [[ $EUID == 0 || ! -e ~/.pyenv/bin ]]; then
1150 echo "error: dont be root. make sure pyenv is installed"
1151 return 1
1152 fi
1153 export PATH="$HOME/.pyenv/bin:$PATH"
1154 eval "$(pyenv init -)"
1155 eval "$(pyenv virtualenv-init -)"
1156 }
1157
1158
1159 export GOPATH=$HOME/go
1160 path-add $GOPATH/bin
1161 path-add /usr/local/go/bin
1162
1163 # I have the git repo and a release. either one should work.
1164 # I have both because I was trying to solve an issue that
1165 # turned out to be unrelated.
1166 # ARDUINO_PATH=/a/opt/Arduino/build/linux/work
1167 export ARDUINO_PATH=/a/opt/arduino-1.8.9
1168
1169 # They want to be added to the start, but i think
1170 # that should be avoided unless we really need it.
1171 path-add --end ~/.npm-global
1172
1173 path-add --end $HOME/.cargo/bin
1174
1175 # taken from default changes to bashrc and bash_profile
1176 path-add --end $HOME/.rvm/bin
1177 path-add --end $HOME/.gem/ruby/2.3.0/bin
1178
1179
1180 export BASEFILE_DIR=/a/bin/fai-basefiles
1181
1182 #export ANDROID_HOME=/a/opt/android-home
1183 # https://f-droid.org/en/docs/Installing_the_Server_and_Repo_Tools/
1184 #export USE_SDK_WRAPPER=yes
1185 #PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
1186
1187 # didnt get drush working, if I did, this seems like the
1188 # only good thing to include for it.
1189 # Include Drush completion.
1190 # if [ -f "/home/ian/.drush/drush.complete.sh" ] ; then
1191 # source /home/ian/.drush/drush.complete.sh
1192 # fi
1193
1194
1195 # https://wiki.archlinux.org/index.php/Xinitrc#Autostart_X_at_login
1196 # i added an extra condition as gentoo xorg guide says depending on
1197 # $DISPLAY is fragile.
1198 if [[ ! $DISPLAY && $XDG_VTNR == 1 ]] && shopt -q login_shell && isarch; then
1199 exec startx
1200 fi
1201
1202
1203 # ensure no bad programs appending to this file will have an affect
1204 return 0