fixes and new bashrc func
[distro-setup] / brc
diff --git a/brc b/brc
index 1da002401cabee7634f6b6043615b752b12e5dd1..2d3f198bf2be066363e82d1469a1bdc8c883e79b 100644 (file)
--- a/brc
+++ b/brc
@@ -64,7 +64,7 @@ shopt -s cmdhist
 shopt -s globstar
 
 
-# inside emacs fixes
+# inside emcas fixes
 if [[ $RLC_INSIDE_EMACS ]]; then
     # EMACS is used by bash on startup, but we don't need it anymore.
     # plus I hit a bug in a makefile which inherited it
@@ -170,6 +170,7 @@ source $(dirname $(readlink -f $BASH_SOURCE))/path_add-function
 source /a/bin/log-quiet/logq-function
 path_add /a/exe
 path_add --ifexists --end /a/opt/adt-bundle*/tools /a/opt/adt-bundle*/platform-tools
+export WCDHOME=/a
 # based on readme.debian. dunno if this will break on other distros.
 _x=/usr/share/wcd/wcd-include.sh
 if [[ -e $_x ]]; then source $_x; fi
@@ -269,12 +270,18 @@ _cdiff-prep() {
 
 _khfix_common() {
     local h=${1##*@}
+    local x
     ssh-keygen -R $h -f $(readlink -f ~/.ssh/known_hosts)
-    local x=$(timeout 0.1 ssh -v $1 |& sed -rn "s/debug1: Connecting to $h \[([^\]*)].*/\1/p");
+    x=$(timeout 1 ssh -oBatchMode=yes -v $1 |& sed -rn "s/debug1: Connecting to $h \[([^\]*)].*/\1/p")
+    if [[ ! $x ]]; then
+        echo "khfix: ssh failed"
+        return 1
+    fi
+    echo "khfix: removing key for $x"
     ssh-keygen -R $x -f $(readlink -f ~/.ssh/known_hosts)
 }
 khfix() { # known hosts fix
-    _khfix_common "$@"
+    _khfix_common "$@" || return 1
     ssh $1 :
 }
 khcopy() {
@@ -300,21 +307,6 @@ b() {
     c -
 }
 
-bashrcpush () {
-    local startdir="$PWD"
-    cd ~
-    for x in "$@"; do
-        ssh $x mkdir -p bin/distro-functions/src
-        tar cz bin/semi-private bin/distro-functions/src | ssh $x tar xz
-    done
-    cd $(mktemp -d)
-    command cp /a/c/repos/bash/!(.git|..|.) ~/.gitconfig .
-    for x in "$@"; do
-        tar cz * | ssh $x tar xz
-    done
-    cd "$startdir"
-}
-
 bkrun() {
     # use -p from interactive shell
     btrbk-run -p "$@"
@@ -324,18 +316,57 @@ bfg() { java -jar /a/opt/bfg-1.12.14.jar "$@"; }
 
 btc() {
     local f=/etc/bitcoin/bitcoin.conf
-    bitcoin-cli -$(s grep rpcuser= $f) -$(s grep rpcpassword= $f) "$@"
+    # importprivkey will timeout if using the default of 15 mins.
+    # upped it to 1 hour.
+    bitcoin-cli -rpcclienttimeout=60000 -$(s grep rpcuser= $f) -$(s grep rpcpassword= $f) "$@"
+}
+
+btcusd() {
+    local price
+    price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
+    printf "$%s\n" "$price"
+    if [[ $1 ]]; then
+        printf "$%.2f\n" "$(echo "scale=4; $price * $1"| bc -l)"
+    fi
+}
+usdbtc() {
+    local price
+    price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
+    printf "$%s\n" "$price"
+    if [[ $1 ]]; then
+        # 100 mil satoshi / btc. 8 digits after the 1.
+        printf "%.8f btc\n" "$(echo "scale=10; $1 / $price "| bc -l)"
+    fi
+}
+satoshi() {
+    local price
+    price="$(curl -s https://api.coinbase.com/v2/prices/BTC-USD/spot | jq -r .data.amount)"
+    price=$(echo "scale=10; $price * 0.00000001"| bc -l)
+    printf "$%f\n" "$price"
+    if [[ $1 ]]; then
+        printf "$%.2f\n" "$(echo "scale=10; $price * $1"| bc -l)"
+    fi
 }
 
+
+# c. better cd
 if [[ $RLC_INSIDE_EMACS ]]; then
-    c() { wcd -z 50 -o "$@"; }
+    c() { wcd -c -z 50 -o "$@"; }
 else
     # lets see what the fancy terminal does from time to time
-    c() { wcd -z 50 "$@"; }
+    c() { wcd -c -z 50 "$@"; }
 fi
 
 caa() { git commit --amend --no-edit -a; }
 
+caf() {
+    find -L $1 -type f -not \( -name .svn -prune -o -name .git -prune \
+         -o -name .hg -prune -o -name .editor-backups -prune \
+         -o -name .undo-tree-history -prune \) \
+         -exec bash -lc 'hr; echo "$1"; hr; cat "$1"' _ {} \; 2>/dev/null
+
+}
+
 calc() { echo "scale=3; $*" | bc -l; }
 # no having to type quotes, but also no command history:
 clc() {
@@ -406,6 +437,10 @@ cl() {
     c =
 }
 
+chrome() {
+    CHROMIUM_FLAGS='--enable-remote-extensions' chromium &r
+}
+
 d() { builtin bg; }
 complete -A stopped -P '"%' -S '"' d
 
@@ -455,7 +490,7 @@ dt() {
     date "+%A, %B %d, %r" "$@"
 }
 
-dus() {
+dus() { # du, sorted, default arg of
     du -sh ${@:-*} | sort -h
 }
 
@@ -494,11 +529,60 @@ fa() {
 }
 
 faf() { # find all files
-    find $@ -type f
+    find -L $1 -type f -not \( -name .svn -prune -o -name .git -prune \
+         -o -name .hg -prune -o -name .editor-backups -prune \
+         -o -name .undo-tree-history -prune \) 2>/dev/null
 }
 
 fastboot() { /a/opt/androidsdk/platform-tools/fastboot "$@"; }
 
+
+# List of apps to install/update
+# Create from existing manually installed apps by doing
+# fdroidcl search -i, then manually removing
+# automatically installed/preinstalled apps
+fdroid_pkgs=(
+    at.bitfire.davdroid
+    com.fsck.k9
+    com.ichi2.anki
+    com.notecryptpro
+    com.nutomic.syncthingandroid
+    com.termux
+    de.danoeh.antennapod
+    de.marmaro.krt.ffupdater
+    im.vector.alpha # riot
+    me.ccrama.redditslide
+    net.gaast.giggity
+    net.osmand.plus
+    org.dmfs.tasks # caldav tasks thing
+    org.fdroid.fdroid
+    org.quantumbadger.redreader
+    org.secuso.privacyfriendlyweather
+    org.smssecure.smssecure
+    org.fedorahosted.freeotp
+    com.ghostsq.commander
+    me.tripsit.tripmobile
+    # https://forum.xda-developers.com/android/software-hacking/wip-selinux-capable-superuser-t3216394
+    me.phh.superuser
+)
+fdup() {
+    local -A installed updated
+    local p
+    fdroidcl update
+    for p in $(fdroidcl search -i| grep -o "^\S\+"); do
+        installed[$p]=true
+    done
+    for p in $(fdroidcl search -u| grep -o "^\S\+"); do
+        updated[$p]=false
+    done
+    for p in ${fdroid_pkgs[@]}; do
+        ${installed[$p]:-false} || fdroidcl install $p
+    done
+    for p in ${!installed[@]}; do
+        ${updated[$p]:-true} || fdroidcl upgrade $p
+    done
+}
+
 ff() {
     if type -P firefox &>/dev/null; then
         firefox "$@"
@@ -646,8 +730,15 @@ and works in older versions of git which did not have that."
     echo "${p%%/.git}"
 }
 
-# quit will prompt if the program crashes.
-gmacs() { gdb -ex=r -ex=quit --args emacs "$@"; r; }
+gmacs() {
+    # quit will prompt if the program crashes.
+    gdb -ex=r -ex=quit --args emacs "$@"; r;
+}
+
+gdkill() {
+    # kill the emacs daemon
+    pk1 emacs --daemon
+}
 
 gse() {
     git send-email --notes '--envelope-sender=<ian@iankelling.org>' \
@@ -702,7 +793,7 @@ hl() { # history limit. Write extra history to archive file.
 }
 
 hr() { # horizontal row. used to break up output
-    printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(seq $COLUMNS)
+    printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(seq ${COLUMNS:-60})
     echo
 }
 
@@ -734,7 +825,8 @@ idea() {
 ifn() {
     # insensitive find
     find -L . -not \( -name .svn -prune -o -name .git -prune \
-         -o -name .hg -prune \) -iname "*$**" 2>/dev/null
+         -o -name .hg -prune -o -name .editor-backups -prune \
+         -o -name .undo-tree-history -prune \) -iname "*$**" 2>/dev/null
 }
 
 
@@ -763,7 +855,15 @@ else
     }
 fi
 
+net-dev-info() {
+    e "lspci -nnk|gr -iA2 net"
+    lspci -nnk|gr -iA2 net
+    hr
+    e "s lshw -C network"
+    hr
+    s lshw -C network
 
+}
 
 istext() {
     grep -Il "" "$@" &>/dev/null
@@ -787,30 +887,33 @@ lcn() { locate -i "*$**"; }
 
 lld() { ll -d "$@"; }
 
-low() {  # make filenames all lowercase
-    local x y
-    for x in "$@"; do
-        y=$(tr "[A-Z]" "[a-z]" <<<"$x")
-        [[ $y != $x ]] && mv "$x" "$y"
+low() {  # make filenames lowercase, remove bad chars
+    local f new
+    for f in "$@"; do
+        new="${f,,}" # downcase
+        new="${new//[^[:alnum:]._-]/_}" # sub bad chars
+        new="${new#"${new%%[[:alnum:]]*}"}" # remove leading/trailing non-alnum
+        new="${new%"${new##*[[:alnum:]]}"}"
+        # remove bad underscores, like __ and _._
+        new=$(echo $new | sed -r 's/__+/_/g;s/_+([.-])|([.-])_+/\1/g')
+        safe_rename "$f" "$new" || return 1
     done
+    return 0
 }
 
-
-
-
 lower() { # make first letter of filenames lowercase.
     local x
     for x in "$@"; do
         if [[ ${x::1} == [A-Z] ]]; then
             y=$(tr "[A-Z]" "[a-z]" <<<"${x::1}")"${x:1}"
-            safe_rename "$x" "$y"
+            safe_rename "$x" "$y" || return 1
         fi
     done
 }
 
 
 k() { # history search
-    grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history}  | tail -n 40;
+    grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history}  | tail -n 80;
 }
 
 
@@ -819,6 +922,25 @@ make-targets() {
     make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
 }
 
+mbenable() {
+    mb=$1
+    dst=/m/4e/$1
+    src=/m/md/$1
+    set -x
+    mv -T $src $dst || { set +x; return 1; }
+    ln -s -T $dst $src
+    set +x
+}
+mbdisable() {
+    mb=$1
+    dst=/m/md/$1
+    src=/m/4e/$1
+    set -x
+    if [[ -L $dst ]]; then rm $dst; fi
+    mv -T $src $dst
+    set +x
+}
+
 
 mkc() {
     mkdir "$1"
@@ -846,6 +968,21 @@ pfind() { #find *$1* in $PATH
     find "${pathArray[@]}" -iname "*$1*"
 }
 
+pk1() {
+    local pid
+    pid=($(pgrep -f "$*"))
+    case ${#pid[@]} in
+        1)
+            ps -F $pid
+            m kill $pid
+            ;;
+        0) echo "no pid found" ;;
+        *)
+            ps -F ${pid[@]}
+            ;;
+    esac
+}
+
 pick-trash() {
     # trash-restore lists everything that has been trashed at or below CWD
     # This picks out files just in CWD, not subdirectories,
@@ -869,14 +1006,6 @@ pick-trash() {
     done
 }
 
-postconfin() {
-    local MAPFILE
-    mapfile -t
-    local s
-    [[ $EUID == 0 ]] || s=s
-    $s postconf -ev "${MAPFILE[@]}"
-}
-
 pub() {
     rld /a/h/_site/ li:/var/www/iankelling.org/html
 }
@@ -884,6 +1013,25 @@ pub() {
 pubip() { curl -4s https://icanhazip.com; }
 whatismyip() { pubip; }
 
+pumpa() {
+    # fixes the menu bar in xmonad. this won\'t be needed when xmonad
+    # packages catches up on some changes in future (this is written in
+    # 4/2017)
+    #
+    # geekosaur: so you'll want to upgrade to xmonad 0.13 or else use a
+    # locally modified XMonad.Hooks.ManageDocks that doesn't set the
+    # work area; turns out it's impossible to set correctly if you are
+    # not a fully EWMH compliant desktop environment
+    #
+    # geekosaur: chrome shows one failure mode, qt/kde another, other
+    # gtk apps a third, ... I came up with a setting that works for me
+    # locally but apparently doesn't work for others, so we joined the
+    # other tiling window managers in giving up on setting it at all
+    #
+    xprop -root -remove _NET_WORKAREA
+    command pumpa &r
+}
+
 
 pwgen() {
     # -m = min length
@@ -892,6 +1040,13 @@ pwgen() {
     apg -m 12 -x 16 -t
 }
 
+pwlong() {
+    # -M CLN = use Caps, Lowercase, Numbers
+    # -n 1 = 1 password
+    # -a 1 = use random instead of pronounceable algorithm
+    apg -m 50 -x 70 -n 1 -a 1 -M CLN
+}
+
 
 q() { # start / launch a program in the backround and redir output to null
     "$@" &> /dev/null &
@@ -924,19 +1079,38 @@ rlt() {
 }
 
 rlu() { # [OPTS] HOST PATH
-    # eg rlu -opts frodo /testpath
+    # eg. rlu -opts frodo /testpath
+    # relative paths will expanded with readlink -f.
     # useful for selectively sending dirs which have been synced with unison,
     # where the path is the same on both hosts.
     opts=("${@:1:$#-2}") #  1 to last -2
     path="${@:$#}" # last
     host="${@:$#-1:1}" # last -1
-    if [[ $path == .* ]]; then echo error: need absolut path; return 1; fi
+    if [[ $path == .* ]]; then
+        path=$(readlink -f $path)
+    fi
     # rync here uses checksum instead of time so we don't mess with
     # unison relying on time as much. g is for group, same reason
     # to keep up with unison.
     s rsync -rlpchviog --relative "${opts[@]}" "$path" "root@$host:/";
 }
 
+r2eadd() { # usage: name url
+    # initial setup of rss2email:
+    # r2e new r2e@iankelling.org
+    # that initializes files, and sets default email.
+    # Would have been simpler to just leave it off since i\'m not
+    # using the default email. Symlinks won\'t work, so we use binds.
+    # mkdir /p/c/binds/.config/
+    # mv ~/.config/rss2email.cfg /p/c/binds/.config/
+    # mkdir /p/c/binds/.local/share/
+    # mv ~/.local/share/rss2email.json /p/c/binds/.local/share/
+    # conflink
+    r2e add $1 "$2" $1@r2e.iankelling.org
+    # get up to date and don't send old entries now:
+    r2e run --no-send $1
+}
+r2e() { command r2e -d /p/c/rss2email.json -c /p/c/rss2email.cfg "$@"; }
 
 rspicy() { # usage: HOST DOMAIN
     # connect to spice vm remote host. use vspicy for local host
@@ -968,15 +1142,17 @@ s() {
     fi
 }
 
-safe_rename() {
+safe_rename() { # warn and don't rename if file exists.
+    # mv -n exists, but it's silent
     if [[ $# != 2 ]]; then
         echo safe_rename error: $# args, need 2 >2
         return 1
-    elif [[ $1 != $2 ]]; then
-        if [[ -e $2 ]]; then
-            echo Cannot rename "$1" to "$2" as it already exists.
+    fi
+    if [[ $1 != $2 ]]; then # yes, we want to silently ignore this
+        if [[ -e $2 || -L $2 ]]; then
+            echo "Cannot rename $1 to $2 as it already exists."
         else
-            mv "$1" "$2"
+            mv -vi "$1" "$2"
         fi
     fi
 }
@@ -1141,43 +1317,49 @@ te() {
 
 testmail() {
     declare -gi _seq; _seq+=1
-    echo "test body" | m mail -s "test mail from $HOSTNAME, $_seq" "${1:-root@localhost}"
+    echo "test body" | m mail -s "test mail from $HOSTNAME, $_seq" "${@:-root@localhost}"
+    # for testing to send from an external address, you can do for example
+    # -aFrom:ian@iank.bid web-6fnbs@mail-tester.com
+    # note in exim, you can retry a deferred message
+    # s exim -M MSG_ID
+    # MSG_ID is in /var/log/exim4/mainlog, looks like 1ccdnD-0001nh-EN
 }
 
-tm() {
-    # timer in minutes
-    (sleep $(calc "$@ * 60") && mpv --volume 50 /a/bin/data/alarm.mp3 --loop=no) > /dev/null 2>&1 &
+# use -eW to actually modify mailbox
+testsievelist() {
+    sieve-filter ~/sieve/main.sieve "$@" >/a/tmp/slog 2> >(tail) && sed -rn '/^Performed actions:/{n;n;p}' /a/tmp/slog | sort -u
 }
 
-ts() { # start editing a new file
-    [[ $# != 1 ]] && echo "I need a filename." && return 1
-    local quiet
-    if [[ $- != *i* ]]; then
-        quiet=true
-    fi
-    if [[ $1 == *.c ]]; then
-        e '#include <stdio.h>' >"$1"
-        e '#include <stdlib.h>' >>"$1"
-        e 'int main(int argc, char * argv[]) {' >>"$1"
-        e '    printf( "hello world\n");' >>"$1"
-        e '    return 0;' >>"$1"
-        e '}' >>"$1"
-        e "${1%.c}: $1" > Makefile
-        e "    g++ -ggdb -std=gnu99 -o ${1%.c} $<" >> Makefile
-        e "#!/bin/bash" >run.sh
-        e "./${1%.c}" >>run.sh
-        chmod +x run.sh
-    elif [[ $1 == *.java ]]; then
-        e "public class ${1%.*} {" >"$1"
-        e '    public static void main(String[] args) {' >>"$1"
-        e '            System.out.println("Hello, world!");' >>"$1"
-        e '    }' >>"$1"
-        e '}' >>"$1"
-    else
-        echo "#!/bin/bash" > "$1"
-        chmod +x "$1"
-    fi
-    [[ $quiet ]] || g "$1"
+
+testsieve() {
+    sieve-filter ~/sieve/main.sieve "$@"
+}
+
+testexim() {
+    # testmail above calls sendmail, which is a link to exim/postfix.
+    # it's docs don't say a way of adding an argument
+    # to sendmail to turn on debug output. We could make a wrapper, but
+    # that is a pain. Exim debug args are documented here:
+    # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html
+    #
+    # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-building_and_installing_exim.html
+    # note, for exim daemon, you can turn on debug options by
+    # adding -d, etc to COMMONOPTIONS in
+    # /etc/default/exim4
+    # for testing external mail, you need the to address as final cmdline arg
+    exim -d+tls -t <<'EOF'
+From: root@frodo.lan
+To: ian@mail.iankelling.org
+Subject: Testing Exim
+
+This is a test message.
+EOF
+}
+
+tm() {
+    # timer in minutes
+    # --no-config
+    (sleep $(calc "$@ * 60") && mpv --no-config --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
 }
 
 
@@ -1216,11 +1398,15 @@ psnetns() {
 
 m() { printf "%s\n" "$*";  "$@"; }
 
+
+vpncmd() {
+    m s nsenter -t $(pgrep -f "/usr/sbin/openvpn --suppress-timestamps --nobind --config /etc/openvpn/client/client.conf") -n -m "$@"
+}
+vpnf() {
+    vpncmd gksudo -u ian firefox &r
+}
 vpnbash() {
-    m s nsenter -t $(pgrep openvpn) -n -m bash
-    # note, if we wanted to run a graphical program,
-    # instead of bash, we could use
-    # gksudo -u ${SUDO_USER:-$USER} "$@"
+    vpncmd bash
 }
 
 
@@ -1493,16 +1679,15 @@ fi
 # based on warning from rvmsudo
 export rvmsudo_secure_path=1
 
-# for other script I wrote
-#export ACME_TINY_PATH=/a/opt/acme-tiny
-export ACME_TINY_WRAPPER_CERT_DIR=/p/c/machine_specific/$HOSTNAME/webservercerts
-
 if [[ -s "/usr/local/rvm/scripts/rvm" ]]; then
     source "/usr/local/rvm/scripts/rvm"
 elif [[ -s $HOME/.rvm/scripts/rvm ]]; then
     source $HOME/.rvm/scripts/rvm
 fi
 
+export GOPATH=$HOME/go
+path_add $GOPATH/bin
+
 
 path_add --end ~/.npm-global