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