From 573c12ec8d999a5db4b03277f6ada7f78a46683f Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Tue, 10 Jan 2017 12:25:35 -0800 Subject: [PATCH] make ssh more robust --- .bashrc | 1550 +------------------------------------------------------ brc | 1527 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1541 insertions(+), 1536 deletions(-) create mode 100644 brc diff --git a/.bashrc b/.bashrc index 00198c0..7db792c 100644 --- a/.bashrc +++ b/.bashrc @@ -25,15 +25,19 @@ # commands. when a local script runs an ssh command, this file should not be # sourced by default, but we should be able to override that. # -# so here we test for conditions of a script under ssh and return if so. To test -# for an overriding condition, we have a few options. one is to use an -# environment variable. env variables sent across ssh are strictly limited. ssh -# -t which sets $SSH_TTY, but within a script that won't work because tty -# allocation will fail. We could override an obscure unused LC_var, like -# telephone, but I don't want to run into some edge case where that messes -# things up. we could transfer a file which we could test for, but I can't think -# of a way to make that inherently limited to a single ssh command. I choose to -# set SendEnv and AcceptEnv ssh config vars to allow the environment variable +# So here we test for conditions of a script under ssh and return if so. +# And we don't keep the rest of the code in this file, because even +# though we return, we already parsed the whole code, and as I develop +# the code, the parsing can have errors, which can screw up cronjobs +# etc. To test for an overriding condition, we have a few options. one +# is to use an environment variable. env variables sent across ssh are +# strictly limited. ssh -t which sets $SSH_TTY, but within a script that +# won't work because tty allocation will fail. We could override an +# obscure unused LC_var, like telephone, but I don't want to run into +# some edge case where that messes things up. we could transfer a file +# which we could test for, but I can't think of a way to make that +# inherently limited to a single ssh command. I choose to set SendEnv +# and AcceptEnv ssh config vars to allow the environment variable # BASH_LOGIN_SHELL to propagate across ssh. # assume we want ssh commands to source this file if we are sourcing it, @@ -50,1531 +54,5 @@ if [[ $SSH_CONNECTION ]] \ return else source /etc/profile + source ~/brc fi - - - -# note, to catch errors in functions but not outside, do: -# set -E -o pipefail -# trap return ERR -# trap 'trap ERR' RETURN - - - -############ -# settings # -############ - -CDPATH=. - -set -o pipefail - -# remove all aliases. aliases provided by the system tend to get in the way, -# for example, error happens if I try to define a function the same name as an alias -unalias -a - -# remove gnome keyring warning messages -# there is probably a more proper way, but I didn't find any easily on google -# now using xfce+xmonad instead of vanilla xmonad, so disabling this -#unset GNOME_KEYRING_CONTROL - -# use extra globing features. -shopt -s extglob -# include .files when globbing, but ignore files name . and .. -# setting this also sets dotglob. -# Note, this doesn't work in bash 4.4 anymore, for paths with -# more than 1 directory, like a/b/.foo, since * is fixed to not match / -export GLOBIGNORE=*/.:*/.. - -# broken with bash_completion package. Saw a bug for this once. Don't anymore. -# still broken in wheezy -# still buggered in latest stable from the web, version 2.1 -# perhaps its fixed in newer git version, which fails to make for me -# this note is from 6-2014. -# Also, enabling this before sourcing .bashrc makes PATH be empty. -#shopt -s nullglob - -# make tab on an empty line do nothing -shopt -s no_empty_cmd_completion - -# advanced completion -# http://bash-completion.alioth.debian.org/ -# might be sourced by the system already, but I've noticed it not being sourced before -if ! type _init_completion &> /dev/null && [[ -r "/usr/share/bash-completion/bash_completion" ]]; then - . /usr/share/bash-completion/bash_completion -fi - - -# fix spelling errors for cd, only in interactive shell -shopt -s cdspell -# append history instead of overwritting it -shopt -s histappend -# for compatibility, per gentoo/debian bashrc -shopt -s checkwinsize -# attempt to save multiline single commands as single history entries. -shopt -s cmdhist -# enable ** -shopt -s globstar - - -# inside emacs 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 - unset EMACS - export RLC_INSIDE_EMACS - export PAGER=cat - export MANPAGER=cat - # scp completion does not work, but this doesn't fix it. todo, figure this out - complete -r scp &> /dev/null - # todo, remote file completion fails, figure out how to turn it off - export NODE_DISABLE_COLORS=1 - # This get's rid of ugly terminal escape chars in node repl - # sometime, I'd like to have completion working in emacs shell for node - # the offending chars can be found in lib/readline.js, - # things that do like: - # stream.write('\x1b[' + (x + 1) + 'G'); - # We can remove them and keep readline, for example by doing this - # to start a repl: - #!/usr/bin/env nodejs - # var readline = require('readline'); - # readline.cursorTo = function(a,b,c) {}; - # readline.clearScreenDown = function(a) {}; - # const repl = require('repl'); - # var replServer = repl.start(''); - # - # no prompt, or else readline complete seems to be confused, based - # on our column being different? node probably needs to send - # different kind of escape sequence that is not ugly. Anyways, - # completion doesn't work yet even with the ugly prompt, so whatever - # - export NODE_NO_READLINE=1 - -fi - - -if [[ $- == *i* ]]; then - # for readline-complete.el - if [[ $RLC_INSIDE_EMACS ]]; then - # all for readline-complete.el - stty echo - bind 'set horizontal-scroll-mode on' - bind 'set print-completions-horizontally on' - bind '"\C-i": self-insert' - else - # arrow keys. for other terminals, see http://unix.stackexchange.com/questions/10806/how-to-change-previous-next-word-shortcut-in-bash - if [[ $TERM == "xterm" ]]; then - bind '"\e[1;5C": shell-forward-word' 2>/dev/null - bind '"\e[1;5D": shell-backward-word' 2>/dev/null - else - bind '"\eOc": shell-forward-word' - bind '"\eOd": shell-backward-word' - fi - # terminal keys: C-c, C-z. the rest defined by stty -a are, at least in - # gnome-terminal, overridden by bash, or disabled by the system - stty werase undef lnext undef stop undef start undef - - fi - -fi - - -# history number. History expansion is good. -PS4='$LINENO+ ' -# history file size limit, set to unlimited. -# this needs to be different from the default because -# default HISTFILESIZE is 500 and could clobber our history -HISTFILESIZE= -# max commands 1 session can append/read from history -HISTSIZE=100000 -# my own history size limit based on lines -HISTFILELINES=1000000 -HISTFILE=$HOME/.bh -# the time format display when doing the history command -# also, setting this makes the history file record time -# of each command as seconds from the epoch -HISTTIMEFORMAT="%I:%M %p %m/%d " -# consecutive duplicate lines don't go in history -HISTCONTROL=ignoredups -# works in addition to HISTCONTROL to do more flexible things -# it could also do the same things as HISTCONTROL and thus replace it, -# but meh. dunno why, but just " *" does glob expansion, so use [ ] to avoid it. -HISTIGNORE='k *:[ ]*' - -export BC_LINE_LENGTH=0 - - -# note, if I use a machine I don't want files readable by all users, set -# umask 077 # If fewer than 4 digits are entered, leading zeros are assumed - -C_DEFAULT_DIR=/a - - -################### -## include files ### -################### -for _x in /a/bin/distro-functions/src/* /a/bin/!(githtml)/*-function?(s); do - source "$_x" -done -unset _x -# so I can share my bashrc -for x in /a/bin/bash_unpublished/source-!(.#*); do source $x; done -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 -# 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 - - -############### -### aliases ### -############### - -# very few aliases, functions are always preferred. - -# ancient stuff. -if [[ $OS == Windows_NT ]]; then - alias ffs='cygstart "/c/Program Files (x86)/Mozilla Firefox/firefox.exe" -P scratch' - export DISPLAY=nt - alias j='command cygpath' - alias t='command cygstart' - alias cygstart='echo be quick, use the alias "t" instead :\)' - alias cygpath='echo be quick, use the alias "j" instead :\)' -fi - - - -# keep this in mind? good for safety. -# alias cp='cp -i' -# alias mv='mv -i' - - -# remove any default aliases for these -unalias ls ll grep &>/dev/null ||: - - - - - - - - - -##################### -### functions #### -##################### - - -..() { c ..; } -...() { c ../..; } -....() { c ../../..; } -.....() { c ../../../..; } -......() { c ../../../../..; } - - -# file cut copy and paste, like the text buffers :) -# I havn't tested these. -_fbufferinit() { # internal use by - ! [[ $my_f_tempdir ]] && my_f_tempdir=$(mktemp -d) - rm -rf "$my_f_tempdir"/* -} -fcp() { # file cp - _fbufferinit - cp "$@" "$my_f_tempdir"/ -} -fct() { # file cut - _fbufferinit - mv "$@" "$my_f_tempdir"/ -} -fpst() { # file paste - [[ $2 ]] && { echo too many arguments; return 1; } - target=${1:-.} - cp "$my_f_tempdir"/* "$target" -} - - -# todo, update this -complete -F _longopt la lower low rlt rld rl lld ts ll dircp ex fcp fct fpst gr - - -_cdiff-prep() { - # join options which are continued to multiples lines onto one line - local first=true - grep -vE '^([ \t]*#|^[ \t]*$)' "$1" | while IFS= read -r line; do - # remove leading spaces/tabs. assumes extglob - if [[ $line == "[ ]*" ]]; then - line="${line##+( )}" - fi - if $first; then - pastline="$line" - first=false - elif [[ $line == *=* ]]; then - echo "$pastline" >> "$2" - pastline="$line" - else - pastline="$pastline $line" - fi - done - echo "$pastline" >> "$2" -} - -_khfix_common() { - local h=${1##*@} - 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"); - ssh-keygen -R $x -f $(readlink -f ~/.ssh/known_hosts) -} -khfix() { # known hosts fix - _khfix_common "$@" - ssh $1 : -} -khcopy() { - _khfix_common "$@" - ssh-copy-id $1 -} - -a() { - beet "${@}" -} - -ack() { ack-grep "$@"; } - -astudio() { - # googling android emulator libGL error: failed to load driver: r600 - # lead to http://stackoverflow.com/a/36625175/14456 - export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 - /a/opt/android-studio/bin/studio.sh "$@" &r; -} - -b() { - # backwards - 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 "$@" -} - -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) "$@" -} - -if [[ $RLC_INSIDE_EMACS ]]; then - c() { wcd -z 50 -o "$@"; } -else - # lets see what the fancy terminal does from time to time - c() { wcd -z 50 "$@"; } -fi - -caa() { git commit --amend --no-edit -a; } - -calc() { echo "scale=3; $*" | bc -l; } -# no having to type quotes, but also no command history: -clc() { - local x - read -r x - echo "scale=3; $x" | bc -l -} - -cam() { - git commit -am "$*" -} - -ccat () { # config cat. see a config without extra lines. - grep '^\s*[^[:space:]#]' "$@" -} - -cdiff() { - # diff config files, - # setup for format of postfix, eg: - # option = stuff[,] - # [more stuff] - local pastline - local unified="$(mktemp)" - local f1="$(mktemp)" - local f2="$(mktemp)" - _cdiff-prep "$1" "$f1" - _cdiff-prep "$2" "$f2" - cat "$f1" "$f2" | grep -Po '^[^=]+=' | sort | uniq > "$unified" - while IFS= read -r line; do - # the default bright red / blue doesn't work in emacs shell - dwdiff -cblue,red -A best -d " ," <(grep "^$line" "$f1" || echo ) <(grep "^$line" "$f2" || echo ) | colordiff - done < "$unified" -} - -cgpl() -{ - if (($#)); then - cp /a/bin/data/COPYING "$@" - else - cp /a/bin/data/COPYING . - fi -} -capache() -{ - if (($#)); then - cp /a/bin/data/LICENSE "$@" - else - cp /a/bin/data/LICENSE . - fi -} -chown() { - # makes it so chown -R symlink affects the symlink and its target. - if [[ $1 == -R ]]; then - shift - command chown -h "$@" - command chown -R "$@" - else - command chown "$@" - fi -} - -cim() { - git commit -m "$*" -} - -cl() { - # choose recent directory. cl = cd list - c = -} - -d() { builtin bg; } -complete -A stopped -P '"%' -S '"' d - -dat() { # do all tee, for more complex scripts - tee >(ssh frodo bash -l) >(bash -l) >(ssh x2 bash -l) >(ssh tp bash -l) -} -da() { # do all - local host - "$@" - for host in x2 tp treetowl; do - ssh $host "$@" - done -} - -dc() { - diff --strip-trailing-cr -w "$@" # diff content -} - -debian_pick_mirror () { - # netselect-apt finds a fast mirror. - # but we need to replace the mirrors ourselves, - # because it doesn't do that. best it can do is - # output a basic sources file - # here we get the server it found, get the main server we use - # then substitute all instances of one for the other in the sources file - # and backup original to /etc/apt/sources.list-original. - # this is idempotent. the only way to identify debian sources is to - # note the original server, so we put it in a comment so we can - # identify it later. - local file=$(mktemp -d)/f # safe way to get file name without creating one - sudo netselect-apt -o "$file" || return 1 - url=$(grep ^\\w $file | head -n1 | awk '{print $2}') - sudo cp -f /etc/apt/sources.list /etc/apt/sources.list-original - sudo sed -ri "/http.us.debian.org/ s@( *[^ #]+ +)[^ ]+([^#]+).*@\1$url\2# http.us.debian.org@" /etc/apt/sources.list - sudo apt-get update -} - -despace() { - local x y - for x in "$@"; do - y="${x// /_}" - safe_rename "$x" "$y" - done -} - -dt() { - date "+%A, %B %d, %r" "$@" -} - -dus() { - du -sh ${@:-*} | sort -h -} - - - -e() { echo "$@"; } - - -ediff() { - [[ ${#@} == 2 ]] || { echo "error: ediff requires 2 arguments"; return 1; } - emacs --eval "(ediff-files \"$1\" \"$2\")" -} - - -envload() { # load environment from a previous: export > file - local file=${1:-$HOME/.${USER}_env} - eval "$(export | sed 's/^declare -x/export -n/')" - while IFS= read -r line; do - # declare -x makes variables local to a function - eval ${line/#declare -x/export} - done < "$file" -} - -f() { - # cd forward - c + -} - -fa() { - # find array. make an array of file names found by find into $x - # argument: find arguments - # return: find results in an array $x - while read -rd ''; do - x+=("$REPLY"); - done < <(find "$@" -print0); -} - -faf() { # find all files - find $@ -type f -} - -fastboot() { /a/opt/androidsdk/platform-tools/fastboot "$@"; } - -ff() { - if type -P firefox &>/dev/null; then - firefox "$@" - else - iceweasel "$@" - fi -} - - - -fn() { - firefox -P alt "$@" >/dev/null 2>&1 -} - - -fsdiff () { - local missing=false - local dname="${PWD##*/}" - local m="/a/tmp/$dname-missing" - local d="/a/tmp/$dname-diff" - [[ -e $d ]] && rm "$d" - [[ -e $m ]] && rm "$m" - local msize=0 - local fsfile - while read -r line; do - fsfile="$1${line#.}" - if [[ -e "$fsfile" ]]; then - md5diff "$line" "$fsfile" && tee -a "/a/tmp/$dname-diff" <<< "$fsfile $line" - else - missing=true - echo "$line" >> "$m" - msize=$((msize + 1)) - fi - done < <(find -type f ) - if $missing; then - echo "$m" - (( msize <= 100 )) && cat $m - fi -} -fsdiff-test() { - # expected output, with different tmp dirs - # /tmp/tmp.HDPbwMqdC9/c/d ./c/d - # /a/tmp/tmp.qLDkYxBYPM-missing - # ./b - cd $(mktemp -d) - echo ok > a - echo nok > b - mkdir c - echo ok > c/d - local x=$(mktemp -d) - mkdir $x/c - echo different > $x/c/d - echo ok > $x/a - fsdiff $x -} -rename-test() { - # test whether missing files were renamed, generally for use with fsdiff - # $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir - # echos non-renamed files - local x y found - unset sums - for x in "$2"/*; do - { sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null - done - while read -r line; do - { missing_sum=$(md5sum < "$line") ; } 2>/dev/null - renamed=false - for x in "${sums[@]}"; do - if [[ $missing_sum == "$x" ]]; then - renamed=true - break - fi - done - $renamed || echo "$line" - done < "$1" - return 0 -} - -feh() { - # F = fullscren, z = random, Z = auto zoom - command feh -FzZ "$@" -} - -funce() { - # like -e for functions. returns on error. - # at the end of the function, disable with: - # trap ERR - trap 'echo "${BASH_COMMAND:+BASH_COMMAND=\"$BASH_COMMAND\" } -${FUNCNAME:+FUNCNAME=\"$FUNCNAME\" }${LINENO:+LINENO=\"$LINENO\" }\$?=$?" -trap ERR -return' ERR -} - - -fw() { - firefox -P default "$@" >/dev/null 2>&1 -} - -getdir () { - local help="Usage: getdir [--help] PATH -Output the directory of PATH, or just PATH if it is a directory." - if [[ $1 == --help ]]; then - echo "$help" - return 0 - fi - if [[ $# -ne 1 ]]; then - echo "getdir error: expected 1 argument, got $#" - return 1 - fi - if [[ -d $1 ]]; then - echo "$1" - else - local dir="$(dirname "$1")" - if [[ -d $dir ]]; then - echo "$dir" - else - echo "getdir error: directory does not exist" - return 1 - fi - fi -} - -git_empty_branch() { # start an empty git branch. carefull, it deletes untracked files. - [[ $# == 1 ]] || { echo 'need a branch name!'; return 1;} - local gitroot - gitroot || return 1 # function to set gitroot - builtin cd "$gitroot" - git symbolic-ref HEAD refs/heads/$1 - rm .git/index - git clean -fdx -} - -gitroot() { - local help="Usage: gitroot [--help] -Print the full path to the root of the current git repo - -Handles being within a .git directory, unlike git rev-parse --show-toplevel, -and works in older versions of git which did not have that." - if [[ $1 == --help ]]; then - echo "$help" - return - fi - local p=$(git rev-parse --git-dir) || { echo "error: not in a git repo" ; return 1; } - [[ $p != /* ]] && p=$PWD - echo "${p%%/.git}" -} - -# quit will prompt if the program crashes. -gmacs() { gdb -ex=r -ex=quit --args emacs "$@"; r; } - -gse() { - git send-email --notes '--envelope-sender=' \ - --suppress-cc=self "$@" -} - -gr() { - grep -iIP --color=auto "$@" -} - -grr() { - if [[ ${#@} == 1 ]]; then - grep -riIP --color=auto "$@" . - else - grep -riIP --color=auto "$@" - fi -} - -hstatus() { - # do git status on published repos - cd /a/bin/githtml - for x in !(forks) forks/* ian-specific/*; do - cd `readlink -f $x`/.. - hr - echo $x - i status - cd /a/bin/githtml - done -} - -hl() { # history limit. Write extra history to archive file. - # todo: this is not working or not used currently - local max_lines linecount tempfile prune_lines x - local harchive="${HISTFILE}_archive" - for x in "$HISTFILE" "$harchive"; do - [[ -e $x ]] || { touch "$x" && echo "notice from hl(): creating $x"; } - if [[ ! $x || ! -e $x || ! -w $x || $(stat -c "%u" "$x") != $EUID ]]; then - echo "error in hl: history file \$x:$x no good" - return 1 - fi - done - history -a # save history - max_lines=$HISTFILELINES - [[ $max_lines =~ ^[0-9]+$ ]] || { echo "error in hl: failed to get max line count"; return 1; } - linecount=$(wc -l < $HISTFILE) # pipe so it doesn't output a filename - [[ $linecount =~ ^[0-9]+$ ]] || { echo "error in hl: wc failed"; return 1; } - if (($linecount > $max_lines)); then - prune_lines=$(($linecount - $max_lines)) - head -n $prune_lines "$HISTFILE" >> "$harchive" \ - && sed --follow-symlinks -ie "1,${prune_lines}d" $HISTFILE - fi -} - -hr() { # horizontal row. used to break up output - printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(seq $COLUMNS) - echo -} - -hrcat() { local f; for f; do [[ -f $f ]] || continue; hr; echo "$f"; cat "$f"; done } - - -i() { git "$@"; } -# modified from ~/local/bin/git-completion.bash -# other completion commands are mostly taken from bash_completion package -complete -o bashdefault -o default -o nospace -F _git i 2>/dev/null \ - || complete -o default -o nospace -F _git i - -if ! type service &>/dev/null; then - service() { - echo actually running: systemctl $2 $1 - systemctl $2 $1 - } -fi - -ic() { - # fast commit all - git commit -am "$*" -} - -idea() { - /a/opt/idea-IC-163.7743.44/bin/idea.sh "$@" &r -} - -ifn() { - # insensitive find - find -L . -not \( -name .svn -prune -o -name .git -prune \ - -o -name .hg -prune \) -iname "*$**" 2>/dev/null -} - - -if [[ $OS == Windows_NT ]]; then - # cygstart wrapper - cs() { - cygstart "$@" & - } - xp() { - explorer.exe . - } - # launch - o() { - local x=(*$1*) - (( ${#x[#]} > 1 )) && { echo "warning ${#x[#]} matches found"; sleep 1; } - cygstart *$1* & - } -else - o() { - if type gvfs-open &> /dev/null ; then - gvfs-open "$@" - else - xdg-open "$@" - fi - # another alternative is run-mailcap - } -fi - - - -istext() { - grep -Il "" "$@" &>/dev/null -} - -jtail() { - journalctl -n 10000 -f "$@" | grep -Evi "^(\S+\s+){4}(sudo|sshd|cron)" -} - - -l() { - if [[ $PWD == /[iap] ]]; then - command ls -A --color=auto -I lost+found "$@" - else - command ls -A --color=auto "$@" - fi -} - - -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" - done -} - - - - -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" - fi - done -} - - -k() { # history search - grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | tail -n 40; -} - - -make-targets() { - # show make targets, via http://stackoverflow.com/questions/3063507/list-goals-targets-in-gnu-make - make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}' -} - - -mkc() { - mkdir "$1" - c "$1" -} - -mkdir() { command mkdir -p "$@"; } - -pithos() { - cd / - export PYTHONPATH=/a/opt/Pithosfly - python3 -m pithos&r -} - -pakaraoke() { - # from http://askubuntu.com/questions/456021/remove-vocals-from-mp3-and-get-only-instrumentals - 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 -} - - -pfind() { #find *$1* in $PATH - [[ $# != 1 ]] && { echo requires 1 argument; return 1; } - local pathArray - IFS=: pathArray=($PATH); unset IFS - find "${pathArray[@]}" -iname "*$1*" -} - -pick-trash() { - # trash-restore lists everything that has been trashed at or below CWD - # This picks out files just in CWD, not subdirectories, - # which also match grep $1, usually use $1 for a time string - # which you get from running restore-trash once first - local name x ask - local nth=1 - # last condition is to not ask again for ones we skipped - while name="$( echo | restore-trash | gr "$PWD/[^/]\+$" | gr "$1" )" \ - && [[ $name ]] && (( $(wc -l <<<"$name") >= nth )); do - name="$(echo "$name" | head -n $nth | tail -n 1 )" - read -p "$name [Y/n] " ask - if [[ ! $ask || $ask == [Yy] ]]; then - x=$( echo "$name" | gr -o "^\s*[0-9]*" ) - echo $x | restore-trash > /dev/null - elif [[ $ask == [Nn] ]]; then - nth=$((nth+1)) - else - return - fi - 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 -} - -pubip() { curl -4s https://icanhazip.com; } -whatismyip() { pubip; } - - -pwgen() { - # -m = min length - # -x = max length - # -t = print pronunciation - apg -m 12 -x 16 -t -} - - -q() { # start / launch a program in the backround and redir output to null - "$@" &> /dev/null & -} - -r() { - exit "$@" 2>/dev/null -} - -rbpipe() { rbt post -o --diff-filename=- "$@"; } -rbp() { rbt post -o "$@"; } - -rl() { - # rsync, root is required to keep permissions right. - # rsync --archive --human-readable --verbose --itemize-changes --checksum \(-ahvic\) \ - # --no-times --delete - # basically, make an exact copy, use checksums instead of file times to be more accurate - rsync -ahvic --delete "$@" -} -rld() { - # like rlu, but don't delete files on the target end which - # do not exist on the original end. - rsync -ahvic "$@" -} -complete -F _rsync -o nospace rld rl rlt - -rlt() { - # rl without preserving modification time. - rsync -ahvic --delete --no-t "$@" -} - -rlu() { # [OPTS] HOST PATH - # eg rlu -opts frodo /testpath - # 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 - # 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:/"; -} - - -rspicy() { # usage: HOST DOMAIN - # connect to spice vm remote host. use vspicy for local host - local port=$(ssh $1<2 - return 1 - elif [[ $1 != $2 ]]; then - if [[ -e $2 ]]; then - echo Cannot rename "$1" to "$2" as it already exists. - else - mv "$1" "$2" - fi - fi -} - - -sb() { # sudo bash -c - # use sb instead of s is for sudo redirections, - # eg. sb 'echo "ok fine" > /etc/file' - local SUDOD="$PWD" - sudo -i bash -c "$@" -} -complete -F _root_command s sb - -scssl() { - # s gem install scss-lint - pushd /a/opt/thoughtbot-guides - git pull --stat - popd - scss-lint -c /a/opt/thoughtbot-guides/style/sass/.scss-lint.yml "$@" -} - -ser() { - local s; [[ $EUID != 0 ]] && s=sudo - if type -p systemctl &>/dev/null; then - $s systemctl $1 $2 - else - $s service $2 $1 - fi -} - -sgo() { # service go - service=$1 - ser restart $service - if type -p systemctl &>/dev/null; then - ser enable $service - fi -} - - -shellck() { - # 2086 = unquoted $var - # 2046 = unquoted $(cmd) - # i had -x as an arg, but debian testing(stretch) doesn't support it - shellcheck -e 2086,2046,2068,2006,2119 "$@" -} - - -slog() { - # log with script. timing is $1.t and script is $1.s - # -l to save to ~/typescripts/ - # -t to add a timestamp to the filenames - local logdir do_stamp arg_base - (( $# >= 1 )) || { echo "arguments wrong"; return 1; } - logdir="/a/dt/" - do_stamp=false - while getopts "lt" option - do - case $option in - l ) arg_base=$logdir ;; - t ) do_stamp=true ;; - esac - done - shift $(($OPTIND - 1)) - arg_base+=$1 - [[ -e $logdir ]] || mkdir -p $logdir - $do_stamp && arg_base+=$(date +%F.%T%z) - script -t $arg_base.s 2> $arg_base.t -} -splay() { # script replay - #logRoot="$HOME/typescripts/" - #scriptreplay "$logRoot$1.t" "$logRoot$1.s" - scriptreplay "$1.t" "$1.s" -} - -sr() { - # sudo redo. be aware, this command may not work right on strange distros or earlier software - if [[ $# == 0 ]]; then - sudo -E bash -c -l "$(history -p '!!')" - else - echo this command redos last history item. no argument is accepted - fi -} - -srm () { - # with -ll, less secure but faster. - command srm -ll "$@" -} - -srun() { - scp $2 $1:/tmp - ssh $1 /tmp/${2##*/} "${@:2}" -} - -swap() { - local tmp - tmp=$(mktemp) - mv $1 $tmp - mv $2 $1 - mv $tmp $2 -} - -t() { - local x - local -a args - if type -t trash-put >/dev/null; then - # skip args that don't exist, or else trash-put will have an error - for x in "$@"; do - if [[ -e $x || -L $x ]]; then - args+=("$x") - fi - done - [[ ! ${args[@]} ]] || trash-put "${args[@]}" - else - rm -rf "$@" - fi -} - - -tclock() { - clear - date +%l:%_M - len=60 - # this goes to full width - #len=${1:-$((COLUMNS -7))} - x=1 - while true; do - if (( x == len )); then - end=true - d="$(date +%l:%_M) " - else - end=false - d=$(date +%l:%M:%_S) - fi - echo -en "\r" - echo -n "$d" - for ((i=0; i /dev/null 2>&1 & -} - -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 ' >"$1" - e '#include ' >>"$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" -} - - -tu() { - local s; - local dir="$(dirname "$1")" - if [[ -e $1 && ! -w $1 || ! -w $(dirname "$1") ]]; then - s=s; - fi - $s teeu "$@" -} - -tx() { # toggle set -x, and the prompt so it doesn't spam - if [[ $- == *x* ]]; then - set +x - PROMPT_COMMAND=prompt_command - else - unset PROMPT_COMMAND - PS1="\w \$ " - set -x - fi -} - -psnetns() { - # show all processes in the network namespace $1. - # blank entries appear to be subprocesses/threads - local x netns - netns=$1 - ps -w | head -n 1 - s find -L /proc/[1-9]*/task/*/ns/net -samefile /run/netns/$netns | cut -d/ -f5 | \ - while read l; do - x=$(ps -w --no-headers -p $l); - if [[ $x ]]; then echo "$x"; else echo $l; fi; - done -} - -m() { printf "%s\n" "$*"; "$@"; } - -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} "$@" -} - - -trg() { transmission-remote-gtk&r; } - -# transmission() { -# local pid=$(cat /var/lib/transmission-daemon/transmission-daemon.pid) -# if [[ $pid && -e /proc/$pid ]]; then -# echo "noop. already running." -# return -# fi - -# local NAME=transmission-daemon -# local DAEMON=/usr/bin/$NAME -# local duser=debian-transmission - -# [ -e /etc/default/$NAME ] && . /etc/default/$NAME -# s ip netns exec vpn sudo -u $duser ionice -c 3 nice -n 19 $DAEMON $OPTIONS -# } - -virshrm() { - for x in "$@"; do virsh destroy "$x"; virsh undefine "$x"; done -} - -vm-set-listen(){ - local t=$(mktemp) - local vm=$1 - local ip=$2 - s virsh dumpxml $vm | sed -r "s/( /dev/null; then - __git_ps1() { - : - } - fi - - # this needs to come before next ps1 stuff - # this stuff needs bash 4, feb 2009, - # old enough to no longer condition on $BASH_VERSION anymore - shopt -s autocd - shopt -s dirspell - PS1='\w' - if [[ $- == *i* ]] && [[ ! $RLC_INSIDE_EMACS ]]; then - PROMPT_DIRTRIM=2 - bind -m vi-command B:shell-backward-word - bind -m vi-command W:shell-forward-word - fi - - if [[ $SSH_CLIENT ]]; then - PS1="\h $PS1" - fi - - prompt_command() { - local return=$? # this MUST COME FIRST - local psc pst ps_char ps_color stale_subvol - unset IFS - history -a # save history - - # for titlebar - if [[ ! $DESKTOP_SESSION == xmonad && $TERM == *(screen*|xterm*|rxvt*) ]]; then - # from the screen man page - if [[ $TERM == screen* ]]; then - local title_escape="\033]..2;" - else - local title_escape="\033]0;" - fi - echo -ne "$title_escape${PWD/#$HOME/~} $USER@$HOSTNAME\007" - fi - - - case $return in - 0) ps_color="$(get_term_color blue)" - ps_char='\$' - ;; - 1) ps_color="$(get_term_color green)" - ps_char="$return \\$" - ;; - *) ps_color="$(get_term_color yellow)" - ps_char="$return \\$" - ;; - esac - if [[ ! -O . ]]; then # not owner - if [[ -w . ]]; then # writable - ps_color="$(get_term_color bold red)" - else - ps_color="$(get_term_color bold green)" - fi - fi - # I would set nullglob, but bash has had bugs where that - # doesn't work if not in top level. - if [[ -e /nocow/btrfs-stale ]] && ((`ls -AUq /nocow/btrfs-stale|wc -l`)); then - ps_char="! $ps_char" - fi - PS1="${PS1%"${PS1#*[wW]}"} \[$ps_color\]$ps_char\[$(get_term_color nocolor)\] " - # emacs completion doesn't like the git prompt atm, so disabling it. - #PS1="${PS1%"${PS1#*[wW]}"}$(__git_ps1 ' (%s)') \[$ps_color\]$ps_char\[$(get_term_color nocolor)\] " - } - PROMPT_COMMAND=prompt_command -fi - - - -########################################### -# stuff that makes sense to be at the end # -########################################### -if [[ "$SUDOD" ]]; then - cd "$SUDOD" - unset SUDOD -elif [[ -d /a ]] && [[ $PWD == $HOME ]] && [[ $- == *i* ]]; then - cd /a -fi - - -# best practice -unset IFS - - -# if someone exported $SOE, catch errors -if [[ $SOE ]]; then - errcatch -fi - -# I'd prefer to have system-wide, plus user ruby, due to bug in it -# https://github.com/rubygems/rubygems/pull/1002 -# further problems: installing multi-user ruby and user ruby, -# you don't get multi-user ruby when you sudo to root, unless its sudo -i. -# There a third hybrid form, which passenger error suggested I use, -# but it didn't actually work. - -# in cased I never need this -# rvm for non-interactive shell: modified from https://rvm.io/rvm/basics -#if [[ $(type -t rvm) == file && ! $(type -t ruby) ]]; then -# source $(rvm 1.9.3 do rvm env --path) -#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 - - -path_add --end ~/.npm-global - - -# didn't get drush working, if I did, this seems like the -# only good thing to include for it. -# Include Drush completion. -# if [ -f "/home/ian/.drush/drush.complete.sh" ] ; then -# source /home/ian/.drush/drush.complete.sh -# fi - - -# https://wiki.archlinux.org/index.php/Xinitrc#Autostart_X_at_login -# i added an extra condition as gentoo xorg guide says depending on -# $DISPLAY is fragile. -if [[ ! $DISPLAY && $XDG_VTNR == 1 ]] && shopt -q login_shell && isarch; then - exec startx -fi - - -# ensure no bad programs appending to this file will have an affect -return 0 diff --git a/brc b/brc new file mode 100644 index 0000000..1da0024 --- /dev/null +++ b/brc @@ -0,0 +1,1527 @@ +#!/bin/bash +# this gets sourced. shebang is just for file mode detection + +# note, to catch errors in functions but not outside, do: +# set -E -o pipefail +# trap return ERR +# trap 'trap ERR' RETURN + + + +############ +# settings # +############ + +CDPATH=. + +set -o pipefail + +# remove all aliases. aliases provided by the system tend to get in the way, +# for example, error happens if I try to define a function the same name as an alias +unalias -a + +# remove gnome keyring warning messages +# there is probably a more proper way, but I didn't find any easily on google +# now using xfce+xmonad instead of vanilla xmonad, so disabling this +#unset GNOME_KEYRING_CONTROL + +# use extra globing features. +shopt -s extglob +# include .files when globbing, but ignore files name . and .. +# setting this also sets dotglob. +# Note, this doesn't work in bash 4.4 anymore, for paths with +# more than 1 directory, like a/b/.foo, since * is fixed to not match / +export GLOBIGNORE=*/.:*/.. + +# broken with bash_completion package. Saw a bug for this once. Don't anymore. +# still broken in wheezy +# still buggered in latest stable from the web, version 2.1 +# perhaps its fixed in newer git version, which fails to make for me +# this note is from 6-2014. +# Also, enabling this before sourcing .bashrc makes PATH be empty. +#shopt -s nullglob + +# make tab on an empty line do nothing +shopt -s no_empty_cmd_completion + +# advanced completion +# http://bash-completion.alioth.debian.org/ +# might be sourced by the system already, but I've noticed it not being sourced before +if ! type _init_completion &> /dev/null && [[ -r "/usr/share/bash-completion/bash_completion" ]]; then + . /usr/share/bash-completion/bash_completion +fi + + +# fix spelling errors for cd, only in interactive shell +shopt -s cdspell +# append history instead of overwritting it +shopt -s histappend +# for compatibility, per gentoo/debian bashrc +shopt -s checkwinsize +# attempt to save multiline single commands as single history entries. +shopt -s cmdhist +# enable ** +shopt -s globstar + + +# inside emacs 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 + unset EMACS + export RLC_INSIDE_EMACS + export PAGER=cat + export MANPAGER=cat + # scp completion does not work, but this doesn't fix it. todo, figure this out + complete -r scp &> /dev/null + # todo, remote file completion fails, figure out how to turn it off + export NODE_DISABLE_COLORS=1 + # This get's rid of ugly terminal escape chars in node repl + # sometime, I'd like to have completion working in emacs shell for node + # the offending chars can be found in lib/readline.js, + # things that do like: + # stream.write('\x1b[' + (x + 1) + 'G'); + # We can remove them and keep readline, for example by doing this + # to start a repl: + #!/usr/bin/env nodejs + # var readline = require('readline'); + # readline.cursorTo = function(a,b,c) {}; + # readline.clearScreenDown = function(a) {}; + # const repl = require('repl'); + # var replServer = repl.start(''); + # + # no prompt, or else readline complete seems to be confused, based + # on our column being different? node probably needs to send + # different kind of escape sequence that is not ugly. Anyways, + # completion doesn't work yet even with the ugly prompt, so whatever + # + export NODE_NO_READLINE=1 + +fi + + +if [[ $- == *i* ]]; then + # for readline-complete.el + if [[ $RLC_INSIDE_EMACS ]]; then + # all for readline-complete.el + stty echo + bind 'set horizontal-scroll-mode on' + bind 'set print-completions-horizontally on' + bind '"\C-i": self-insert' + else + # arrow keys. for other terminals, see http://unix.stackexchange.com/questions/10806/how-to-change-previous-next-word-shortcut-in-bash + if [[ $TERM == "xterm" ]]; then + bind '"\e[1;5C": shell-forward-word' 2>/dev/null + bind '"\e[1;5D": shell-backward-word' 2>/dev/null + else + bind '"\eOc": shell-forward-word' + bind '"\eOd": shell-backward-word' + fi + # terminal keys: C-c, C-z. the rest defined by stty -a are, at least in + # gnome-terminal, overridden by bash, or disabled by the system + stty werase undef lnext undef stop undef start undef + + fi + +fi + + +# history number. History expansion is good. +PS4='$LINENO+ ' +# history file size limit, set to unlimited. +# this needs to be different from the default because +# default HISTFILESIZE is 500 and could clobber our history +HISTFILESIZE= +# max commands 1 session can append/read from history +HISTSIZE=100000 +# my own history size limit based on lines +HISTFILELINES=1000000 +HISTFILE=$HOME/.bh +# the time format display when doing the history command +# also, setting this makes the history file record time +# of each command as seconds from the epoch +HISTTIMEFORMAT="%I:%M %p %m/%d " +# consecutive duplicate lines don't go in history +HISTCONTROL=ignoredups +# works in addition to HISTCONTROL to do more flexible things +# it could also do the same things as HISTCONTROL and thus replace it, +# but meh. dunno why, but just " *" does glob expansion, so use [ ] to avoid it. +HISTIGNORE='k *:[ ]*' + +export BC_LINE_LENGTH=0 + + +# note, if I use a machine I don't want files readable by all users, set +# umask 077 # If fewer than 4 digits are entered, leading zeros are assumed + +C_DEFAULT_DIR=/a + + +################### +## include files ### +################### +for _x in /a/bin/distro-functions/src/* /a/bin/!(githtml)/*-function?(s); do + source "$_x" +done +unset _x +# so I can share my bashrc +for x in /a/bin/bash_unpublished/source-!(.#*); do source $x; done +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 +# 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 + + +############### +### aliases ### +############### + +# very few aliases, functions are always preferred. + +# ancient stuff. +if [[ $OS == Windows_NT ]]; then + alias ffs='cygstart "/c/Program Files (x86)/Mozilla Firefox/firefox.exe" -P scratch' + export DISPLAY=nt + alias j='command cygpath' + alias t='command cygstart' + alias cygstart='echo be quick, use the alias "t" instead :\)' + alias cygpath='echo be quick, use the alias "j" instead :\)' +fi + + + +# keep this in mind? good for safety. +# alias cp='cp -i' +# alias mv='mv -i' + + +# remove any default aliases for these +unalias ls ll grep &>/dev/null ||: + + + + + + + + + +##################### +### functions #### +##################### + + +..() { c ..; } +...() { c ../..; } +....() { c ../../..; } +.....() { c ../../../..; } +......() { c ../../../../..; } + + +# file cut copy and paste, like the text buffers :) +# I havn't tested these. +_fbufferinit() { # internal use by + ! [[ $my_f_tempdir ]] && my_f_tempdir=$(mktemp -d) + rm -rf "$my_f_tempdir"/* +} +fcp() { # file cp + _fbufferinit + cp "$@" "$my_f_tempdir"/ +} +fct() { # file cut + _fbufferinit + mv "$@" "$my_f_tempdir"/ +} +fpst() { # file paste + [[ $2 ]] && { echo too many arguments; return 1; } + target=${1:-.} + cp "$my_f_tempdir"/* "$target" +} + + +# todo, update this +complete -F _longopt la lower low rlt rld rl lld ts ll dircp ex fcp fct fpst gr + + +_cdiff-prep() { + # join options which are continued to multiples lines onto one line + local first=true + grep -vE '^([ \t]*#|^[ \t]*$)' "$1" | while IFS= read -r line; do + # remove leading spaces/tabs. assumes extglob + if [[ $line == "[ ]*" ]]; then + line="${line##+( )}" + fi + if $first; then + pastline="$line" + first=false + elif [[ $line == *=* ]]; then + echo "$pastline" >> "$2" + pastline="$line" + else + pastline="$pastline $line" + fi + done + echo "$pastline" >> "$2" +} + +_khfix_common() { + local h=${1##*@} + 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"); + ssh-keygen -R $x -f $(readlink -f ~/.ssh/known_hosts) +} +khfix() { # known hosts fix + _khfix_common "$@" + ssh $1 : +} +khcopy() { + _khfix_common "$@" + ssh-copy-id $1 +} + +a() { + beet "${@}" +} + +ack() { ack-grep "$@"; } + +astudio() { + # googling android emulator libGL error: failed to load driver: r600 + # lead to http://stackoverflow.com/a/36625175/14456 + export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1 + /a/opt/android-studio/bin/studio.sh "$@" &r; +} + +b() { + # backwards + 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 "$@" +} + +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) "$@" +} + +if [[ $RLC_INSIDE_EMACS ]]; then + c() { wcd -z 50 -o "$@"; } +else + # lets see what the fancy terminal does from time to time + c() { wcd -z 50 "$@"; } +fi + +caa() { git commit --amend --no-edit -a; } + +calc() { echo "scale=3; $*" | bc -l; } +# no having to type quotes, but also no command history: +clc() { + local x + read -r x + echo "scale=3; $x" | bc -l +} + +cam() { + git commit -am "$*" +} + +ccat () { # config cat. see a config without extra lines. + grep '^\s*[^[:space:]#]' "$@" +} + +cdiff() { + # diff config files, + # setup for format of postfix, eg: + # option = stuff[,] + # [more stuff] + local pastline + local unified="$(mktemp)" + local f1="$(mktemp)" + local f2="$(mktemp)" + _cdiff-prep "$1" "$f1" + _cdiff-prep "$2" "$f2" + cat "$f1" "$f2" | grep -Po '^[^=]+=' | sort | uniq > "$unified" + while IFS= read -r line; do + # the default bright red / blue doesn't work in emacs shell + dwdiff -cblue,red -A best -d " ," <(grep "^$line" "$f1" || echo ) <(grep "^$line" "$f2" || echo ) | colordiff + done < "$unified" +} + +cgpl() +{ + if (($#)); then + cp /a/bin/data/COPYING "$@" + else + cp /a/bin/data/COPYING . + fi +} +capache() +{ + if (($#)); then + cp /a/bin/data/LICENSE "$@" + else + cp /a/bin/data/LICENSE . + fi +} +chown() { + # makes it so chown -R symlink affects the symlink and its target. + if [[ $1 == -R ]]; then + shift + command chown -h "$@" + command chown -R "$@" + else + command chown "$@" + fi +} + +cim() { + git commit -m "$*" +} + +cl() { + # choose recent directory. cl = cd list + c = +} + +d() { builtin bg; } +complete -A stopped -P '"%' -S '"' d + +dat() { # do all tee, for more complex scripts + tee >(ssh frodo bash -l) >(bash -l) >(ssh x2 bash -l) >(ssh tp bash -l) +} +da() { # do all + local host + "$@" + for host in x2 tp treetowl; do + ssh $host "$@" + done +} + +dc() { + diff --strip-trailing-cr -w "$@" # diff content +} + +debian_pick_mirror () { + # netselect-apt finds a fast mirror. + # but we need to replace the mirrors ourselves, + # because it doesn't do that. best it can do is + # output a basic sources file + # here we get the server it found, get the main server we use + # then substitute all instances of one for the other in the sources file + # and backup original to /etc/apt/sources.list-original. + # this is idempotent. the only way to identify debian sources is to + # note the original server, so we put it in a comment so we can + # identify it later. + local file=$(mktemp -d)/f # safe way to get file name without creating one + sudo netselect-apt -o "$file" || return 1 + url=$(grep ^\\w $file | head -n1 | awk '{print $2}') + sudo cp -f /etc/apt/sources.list /etc/apt/sources.list-original + sudo sed -ri "/http.us.debian.org/ s@( *[^ #]+ +)[^ ]+([^#]+).*@\1$url\2# http.us.debian.org@" /etc/apt/sources.list + sudo apt-get update +} + +despace() { + local x y + for x in "$@"; do + y="${x// /_}" + safe_rename "$x" "$y" + done +} + +dt() { + date "+%A, %B %d, %r" "$@" +} + +dus() { + du -sh ${@:-*} | sort -h +} + + + +e() { echo "$@"; } + + +ediff() { + [[ ${#@} == 2 ]] || { echo "error: ediff requires 2 arguments"; return 1; } + emacs --eval "(ediff-files \"$1\" \"$2\")" +} + + +envload() { # load environment from a previous: export > file + local file=${1:-$HOME/.${USER}_env} + eval "$(export | sed 's/^declare -x/export -n/')" + while IFS= read -r line; do + # declare -x makes variables local to a function + eval ${line/#declare -x/export} + done < "$file" +} + +f() { + # cd forward + c + +} + +fa() { + # find array. make an array of file names found by find into $x + # argument: find arguments + # return: find results in an array $x + while read -rd ''; do + x+=("$REPLY"); + done < <(find "$@" -print0); +} + +faf() { # find all files + find $@ -type f +} + +fastboot() { /a/opt/androidsdk/platform-tools/fastboot "$@"; } + +ff() { + if type -P firefox &>/dev/null; then + firefox "$@" + else + iceweasel "$@" + fi +} + + + +fn() { + firefox -P alt "$@" >/dev/null 2>&1 +} + + +fsdiff () { + local missing=false + local dname="${PWD##*/}" + local m="/a/tmp/$dname-missing" + local d="/a/tmp/$dname-diff" + [[ -e $d ]] && rm "$d" + [[ -e $m ]] && rm "$m" + local msize=0 + local fsfile + while read -r line; do + fsfile="$1${line#.}" + if [[ -e "$fsfile" ]]; then + md5diff "$line" "$fsfile" && tee -a "/a/tmp/$dname-diff" <<< "$fsfile $line" + else + missing=true + echo "$line" >> "$m" + msize=$((msize + 1)) + fi + done < <(find -type f ) + if $missing; then + echo "$m" + (( msize <= 100 )) && cat $m + fi +} +fsdiff-test() { + # expected output, with different tmp dirs + # /tmp/tmp.HDPbwMqdC9/c/d ./c/d + # /a/tmp/tmp.qLDkYxBYPM-missing + # ./b + cd $(mktemp -d) + echo ok > a + echo nok > b + mkdir c + echo ok > c/d + local x=$(mktemp -d) + mkdir $x/c + echo different > $x/c/d + echo ok > $x/a + fsdiff $x +} +rename-test() { + # test whether missing files were renamed, generally for use with fsdiff + # $1 = fsdiff output file, $2 = directory to compare to. pwd = fsdiff dir + # echos non-renamed files + local x y found + unset sums + for x in "$2"/*; do + { sums+=( "$(md5sum < "$x")" ) ; } 2>/dev/null + done + while read -r line; do + { missing_sum=$(md5sum < "$line") ; } 2>/dev/null + renamed=false + for x in "${sums[@]}"; do + if [[ $missing_sum == "$x" ]]; then + renamed=true + break + fi + done + $renamed || echo "$line" + done < "$1" + return 0 +} + +feh() { + # F = fullscren, z = random, Z = auto zoom + command feh -FzZ "$@" +} + +funce() { + # like -e for functions. returns on error. + # at the end of the function, disable with: + # trap ERR + trap 'echo "${BASH_COMMAND:+BASH_COMMAND=\"$BASH_COMMAND\" } +${FUNCNAME:+FUNCNAME=\"$FUNCNAME\" }${LINENO:+LINENO=\"$LINENO\" }\$?=$?" +trap ERR +return' ERR +} + + +fw() { + firefox -P default "$@" >/dev/null 2>&1 +} + +getdir () { + local help="Usage: getdir [--help] PATH +Output the directory of PATH, or just PATH if it is a directory." + if [[ $1 == --help ]]; then + echo "$help" + return 0 + fi + if [[ $# -ne 1 ]]; then + echo "getdir error: expected 1 argument, got $#" + return 1 + fi + if [[ -d $1 ]]; then + echo "$1" + else + local dir="$(dirname "$1")" + if [[ -d $dir ]]; then + echo "$dir" + else + echo "getdir error: directory does not exist" + return 1 + fi + fi +} + +git_empty_branch() { # start an empty git branch. carefull, it deletes untracked files. + [[ $# == 1 ]] || { echo 'need a branch name!'; return 1;} + local gitroot + gitroot || return 1 # function to set gitroot + builtin cd "$gitroot" + git symbolic-ref HEAD refs/heads/$1 + rm .git/index + git clean -fdx +} + +gitroot() { + local help="Usage: gitroot [--help] +Print the full path to the root of the current git repo + +Handles being within a .git directory, unlike git rev-parse --show-toplevel, +and works in older versions of git which did not have that." + if [[ $1 == --help ]]; then + echo "$help" + return + fi + local p=$(git rev-parse --git-dir) || { echo "error: not in a git repo" ; return 1; } + [[ $p != /* ]] && p=$PWD + echo "${p%%/.git}" +} + +# quit will prompt if the program crashes. +gmacs() { gdb -ex=r -ex=quit --args emacs "$@"; r; } + +gse() { + git send-email --notes '--envelope-sender=' \ + --suppress-cc=self "$@" +} + +gr() { + grep -iIP --color=auto "$@" +} + +grr() { + if [[ ${#@} == 1 ]]; then + grep -riIP --color=auto "$@" . + else + grep -riIP --color=auto "$@" + fi +} + +hstatus() { + # do git status on published repos + cd /a/bin/githtml + for x in !(forks) forks/* ian-specific/*; do + cd `readlink -f $x`/.. + hr + echo $x + i status + cd /a/bin/githtml + done +} + +hl() { # history limit. Write extra history to archive file. + # todo: this is not working or not used currently + local max_lines linecount tempfile prune_lines x + local harchive="${HISTFILE}_archive" + for x in "$HISTFILE" "$harchive"; do + [[ -e $x ]] || { touch "$x" && echo "notice from hl(): creating $x"; } + if [[ ! $x || ! -e $x || ! -w $x || $(stat -c "%u" "$x") != $EUID ]]; then + echo "error in hl: history file \$x:$x no good" + return 1 + fi + done + history -a # save history + max_lines=$HISTFILELINES + [[ $max_lines =~ ^[0-9]+$ ]] || { echo "error in hl: failed to get max line count"; return 1; } + linecount=$(wc -l < $HISTFILE) # pipe so it doesn't output a filename + [[ $linecount =~ ^[0-9]+$ ]] || { echo "error in hl: wc failed"; return 1; } + if (($linecount > $max_lines)); then + prune_lines=$(($linecount - $max_lines)) + head -n $prune_lines "$HISTFILE" >> "$harchive" \ + && sed --follow-symlinks -ie "1,${prune_lines}d" $HISTFILE + fi +} + +hr() { # horizontal row. used to break up output + printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(seq $COLUMNS) + echo +} + +hrcat() { local f; for f; do [[ -f $f ]] || continue; hr; echo "$f"; cat "$f"; done } + + +i() { git "$@"; } +# modified from ~/local/bin/git-completion.bash +# other completion commands are mostly taken from bash_completion package +complete -o bashdefault -o default -o nospace -F _git i 2>/dev/null \ + || complete -o default -o nospace -F _git i + +if ! type service &>/dev/null; then + service() { + echo actually running: systemctl $2 $1 + systemctl $2 $1 + } +fi + +ic() { + # fast commit all + git commit -am "$*" +} + +idea() { + /a/opt/idea-IC-163.7743.44/bin/idea.sh "$@" &r +} + +ifn() { + # insensitive find + find -L . -not \( -name .svn -prune -o -name .git -prune \ + -o -name .hg -prune \) -iname "*$**" 2>/dev/null +} + + +if [[ $OS == Windows_NT ]]; then + # cygstart wrapper + cs() { + cygstart "$@" & + } + xp() { + explorer.exe . + } + # launch + o() { + local x=(*$1*) + (( ${#x[#]} > 1 )) && { echo "warning ${#x[#]} matches found"; sleep 1; } + cygstart *$1* & + } +else + o() { + if type gvfs-open &> /dev/null ; then + gvfs-open "$@" + else + xdg-open "$@" + fi + # another alternative is run-mailcap + } +fi + + + +istext() { + grep -Il "" "$@" &>/dev/null +} + +jtail() { + journalctl -n 10000 -f "$@" | grep -Evi "^(\S+\s+){4}(sudo|sshd|cron)" +} + + +l() { + if [[ $PWD == /[iap] ]]; then + command ls -A --color=auto -I lost+found "$@" + else + command ls -A --color=auto "$@" + fi +} + + +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" + done +} + + + + +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" + fi + done +} + + +k() { # history search + grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | tail -n 40; +} + + +make-targets() { + # show make targets, via http://stackoverflow.com/questions/3063507/list-goals-targets-in-gnu-make + make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}' +} + + +mkc() { + mkdir "$1" + c "$1" +} + +mkdir() { command mkdir -p "$@"; } + +pithos() { + cd / + export PYTHONPATH=/a/opt/Pithosfly + python3 -m pithos&r +} + +pakaraoke() { + # from http://askubuntu.com/questions/456021/remove-vocals-from-mp3-and-get-only-instrumentals + 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 +} + + +pfind() { #find *$1* in $PATH + [[ $# != 1 ]] && { echo requires 1 argument; return 1; } + local pathArray + IFS=: pathArray=($PATH); unset IFS + find "${pathArray[@]}" -iname "*$1*" +} + +pick-trash() { + # trash-restore lists everything that has been trashed at or below CWD + # This picks out files just in CWD, not subdirectories, + # which also match grep $1, usually use $1 for a time string + # which you get from running restore-trash once first + local name x ask + local nth=1 + # last condition is to not ask again for ones we skipped + while name="$( echo | restore-trash | gr "$PWD/[^/]\+$" | gr "$1" )" \ + && [[ $name ]] && (( $(wc -l <<<"$name") >= nth )); do + name="$(echo "$name" | head -n $nth | tail -n 1 )" + read -p "$name [Y/n] " ask + if [[ ! $ask || $ask == [Yy] ]]; then + x=$( echo "$name" | gr -o "^\s*[0-9]*" ) + echo $x | restore-trash > /dev/null + elif [[ $ask == [Nn] ]]; then + nth=$((nth+1)) + else + return + fi + 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 +} + +pubip() { curl -4s https://icanhazip.com; } +whatismyip() { pubip; } + + +pwgen() { + # -m = min length + # -x = max length + # -t = print pronunciation + apg -m 12 -x 16 -t +} + + +q() { # start / launch a program in the backround and redir output to null + "$@" &> /dev/null & +} + +r() { + exit "$@" 2>/dev/null +} + +rbpipe() { rbt post -o --diff-filename=- "$@"; } +rbp() { rbt post -o "$@"; } + +rl() { + # rsync, root is required to keep permissions right. + # rsync --archive --human-readable --verbose --itemize-changes --checksum \(-ahvic\) \ + # --no-times --delete + # basically, make an exact copy, use checksums instead of file times to be more accurate + rsync -ahvic --delete "$@" +} +rld() { + # like rlu, but don't delete files on the target end which + # do not exist on the original end. + rsync -ahvic "$@" +} +complete -F _rsync -o nospace rld rl rlt + +rlt() { + # rl without preserving modification time. + rsync -ahvic --delete --no-t "$@" +} + +rlu() { # [OPTS] HOST PATH + # eg rlu -opts frodo /testpath + # 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 + # 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:/"; +} + + +rspicy() { # usage: HOST DOMAIN + # connect to spice vm remote host. use vspicy for local host + local port=$(ssh $1<2 + return 1 + elif [[ $1 != $2 ]]; then + if [[ -e $2 ]]; then + echo Cannot rename "$1" to "$2" as it already exists. + else + mv "$1" "$2" + fi + fi +} + + +sb() { # sudo bash -c + # use sb instead of s is for sudo redirections, + # eg. sb 'echo "ok fine" > /etc/file' + local SUDOD="$PWD" + sudo -i bash -c "$@" +} +complete -F _root_command s sb + +scssl() { + # s gem install scss-lint + pushd /a/opt/thoughtbot-guides + git pull --stat + popd + scss-lint -c /a/opt/thoughtbot-guides/style/sass/.scss-lint.yml "$@" +} + +ser() { + local s; [[ $EUID != 0 ]] && s=sudo + if type -p systemctl &>/dev/null; then + $s systemctl $1 $2 + else + $s service $2 $1 + fi +} + +sgo() { # service go + service=$1 + ser restart $service + if type -p systemctl &>/dev/null; then + ser enable $service + fi +} + + +shellck() { + # 2086 = unquoted $var + # 2046 = unquoted $(cmd) + # i had -x as an arg, but debian testing(stretch) doesn't support it + shellcheck -e 2086,2046,2068,2006,2119 "$@" +} + + +slog() { + # log with script. timing is $1.t and script is $1.s + # -l to save to ~/typescripts/ + # -t to add a timestamp to the filenames + local logdir do_stamp arg_base + (( $# >= 1 )) || { echo "arguments wrong"; return 1; } + logdir="/a/dt/" + do_stamp=false + while getopts "lt" option + do + case $option in + l ) arg_base=$logdir ;; + t ) do_stamp=true ;; + esac + done + shift $(($OPTIND - 1)) + arg_base+=$1 + [[ -e $logdir ]] || mkdir -p $logdir + $do_stamp && arg_base+=$(date +%F.%T%z) + script -t $arg_base.s 2> $arg_base.t +} +splay() { # script replay + #logRoot="$HOME/typescripts/" + #scriptreplay "$logRoot$1.t" "$logRoot$1.s" + scriptreplay "$1.t" "$1.s" +} + +sr() { + # sudo redo. be aware, this command may not work right on strange distros or earlier software + if [[ $# == 0 ]]; then + sudo -E bash -c -l "$(history -p '!!')" + else + echo this command redos last history item. no argument is accepted + fi +} + +srm () { + # with -ll, less secure but faster. + command srm -ll "$@" +} + +srun() { + scp $2 $1:/tmp + ssh $1 /tmp/${2##*/} "${@:2}" +} + +swap() { + local tmp + tmp=$(mktemp) + mv $1 $tmp + mv $2 $1 + mv $tmp $2 +} + +t() { + local x + local -a args + if type -t trash-put >/dev/null; then + # skip args that don't exist, or else trash-put will have an error + for x in "$@"; do + if [[ -e $x || -L $x ]]; then + args+=("$x") + fi + done + [[ ! ${args[@]} ]] || trash-put "${args[@]}" + else + rm -rf "$@" + fi +} + + +tclock() { + clear + date +%l:%_M + len=60 + # this goes to full width + #len=${1:-$((COLUMNS -7))} + x=1 + while true; do + if (( x == len )); then + end=true + d="$(date +%l:%_M) " + else + end=false + d=$(date +%l:%M:%_S) + fi + echo -en "\r" + echo -n "$d" + for ((i=0; i /dev/null 2>&1 & +} + +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 ' >"$1" + e '#include ' >>"$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" +} + + +tu() { + local s; + local dir="$(dirname "$1")" + if [[ -e $1 && ! -w $1 || ! -w $(dirname "$1") ]]; then + s=s; + fi + $s teeu "$@" +} + +tx() { # toggle set -x, and the prompt so it doesn't spam + if [[ $- == *x* ]]; then + set +x + PROMPT_COMMAND=prompt_command + else + unset PROMPT_COMMAND + PS1="\w \$ " + set -x + fi +} + +psnetns() { + # show all processes in the network namespace $1. + # blank entries appear to be subprocesses/threads + local x netns + netns=$1 + ps -w | head -n 1 + s find -L /proc/[1-9]*/task/*/ns/net -samefile /run/netns/$netns | cut -d/ -f5 | \ + while read l; do + x=$(ps -w --no-headers -p $l); + if [[ $x ]]; then echo "$x"; else echo $l; fi; + done +} + +m() { printf "%s\n" "$*"; "$@"; } + +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} "$@" +} + + +trg() { transmission-remote-gtk&r; } + +# transmission() { +# local pid=$(cat /var/lib/transmission-daemon/transmission-daemon.pid) +# if [[ $pid && -e /proc/$pid ]]; then +# echo "noop. already running." +# return +# fi + +# local NAME=transmission-daemon +# local DAEMON=/usr/bin/$NAME +# local duser=debian-transmission + +# [ -e /etc/default/$NAME ] && . /etc/default/$NAME +# s ip netns exec vpn sudo -u $duser ionice -c 3 nice -n 19 $DAEMON $OPTIONS +# } + +virshrm() { + for x in "$@"; do virsh destroy "$x"; virsh undefine "$x"; done +} + +vm-set-listen(){ + local t=$(mktemp) + local vm=$1 + local ip=$2 + s virsh dumpxml $vm | sed -r "s/( /dev/null; then + __git_ps1() { + : + } + fi + + # this needs to come before next ps1 stuff + # this stuff needs bash 4, feb 2009, + # old enough to no longer condition on $BASH_VERSION anymore + shopt -s autocd + shopt -s dirspell + PS1='\w' + if [[ $- == *i* ]] && [[ ! $RLC_INSIDE_EMACS ]]; then + PROMPT_DIRTRIM=2 + bind -m vi-command B:shell-backward-word + bind -m vi-command W:shell-forward-word + fi + + if [[ $SSH_CLIENT ]]; then + PS1="\h $PS1" + fi + + prompt_command() { + local return=$? # this MUST COME FIRST + local psc pst ps_char ps_color stale_subvol + unset IFS + history -a # save history + + # for titlebar + if [[ ! $DESKTOP_SESSION == xmonad && $TERM == *(screen*|xterm*|rxvt*) ]]; then + # from the screen man page + if [[ $TERM == screen* ]]; then + local title_escape="\033]..2;" + else + local title_escape="\033]0;" + fi + echo -ne "$title_escape${PWD/#$HOME/~} $USER@$HOSTNAME\007" + fi + + + case $return in + 0) ps_color="$(get_term_color blue)" + ps_char='\$' + ;; + 1) ps_color="$(get_term_color green)" + ps_char="$return \\$" + ;; + *) ps_color="$(get_term_color yellow)" + ps_char="$return \\$" + ;; + esac + if [[ ! -O . ]]; then # not owner + if [[ -w . ]]; then # writable + ps_color="$(get_term_color bold red)" + else + ps_color="$(get_term_color bold green)" + fi + fi + # I would set nullglob, but bash has had bugs where that + # doesn't work if not in top level. + if [[ -e /nocow/btrfs-stale ]] && ((`ls -AUq /nocow/btrfs-stale|wc -l`)); then + ps_char="! $ps_char" + fi + PS1="${PS1%"${PS1#*[wW]}"} \[$ps_color\]$ps_char\[$(get_term_color nocolor)\] " + # emacs completion doesn't like the git prompt atm, so disabling it. + #PS1="${PS1%"${PS1#*[wW]}"}$(__git_ps1 ' (%s)') \[$ps_color\]$ps_char\[$(get_term_color nocolor)\] " + } + PROMPT_COMMAND=prompt_command +fi + + + +########################################### +# stuff that makes sense to be at the end # +########################################### +if [[ "$SUDOD" ]]; then + cd "$SUDOD" + unset SUDOD +elif [[ -d /a ]] && [[ $PWD == $HOME ]] && [[ $- == *i* ]]; then + cd /a +fi + + +# best practice +unset IFS + + +# if someone exported $SOE, catch errors +if [[ $SOE ]]; then + errcatch +fi + +# I'd prefer to have system-wide, plus user ruby, due to bug in it +# https://github.com/rubygems/rubygems/pull/1002 +# further problems: installing multi-user ruby and user ruby, +# you don't get multi-user ruby when you sudo to root, unless its sudo -i. +# There a third hybrid form, which passenger error suggested I use, +# but it didn't actually work. + +# in cased I never need this +# rvm for non-interactive shell: modified from https://rvm.io/rvm/basics +#if [[ $(type -t rvm) == file && ! $(type -t ruby) ]]; then +# source $(rvm 1.9.3 do rvm env --path) +#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 + + +path_add --end ~/.npm-global + + +# didn't get drush working, if I did, this seems like the +# only good thing to include for it. +# Include Drush completion. +# if [ -f "/home/ian/.drush/drush.complete.sh" ] ; then +# source /home/ian/.drush/drush.complete.sh +# fi + + +# https://wiki.archlinux.org/index.php/Xinitrc#Autostart_X_at_login +# i added an extra condition as gentoo xorg guide says depending on +# $DISPLAY is fragile. +if [[ ! $DISPLAY && $XDG_VTNR == 1 ]] && shopt -q login_shell && isarch; then + exec startx +fi + + +# ensure no bad programs appending to this file will have an affect +return 0 -- 2.30.2