+# Copyright (C) 2016 Ian Kelling
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
# to debug
#set -x
# redirect output to log file. this doesn't work. todo figure out why
# assume we want ssh commands to source this file if we are sourcing it,
# and we haven't specified otherwise already
[[ ! $BASH_LOGIN_SHELL ]] && export BASH_LOGIN_SHELL=true
+#BASH_LOGIN_SHELL=false # temporary override
# first conditions show that we are an ssh command without an interactive shell
if [[ $SSH_CONNECTION ]] \
# use extra globing features.
shopt -s extglob
# include .files when globbing, but ignore files name . and ..
-# setting this also sets dotglob
+# 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.
shopt -s checkwinsize
# attempt to save multiline single commands as single history entries.
shopt -s cmdhist
+# enable **
shopt -s globstar
# 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
###################
## include files ###
###################
-
-for _x in /a/bin/distro-functions/src/* /a/bin/*/*-function; do
+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/*; do source $x; done
+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 $HOME/bin/bash-programs-by-ian/utils
+
###############
### aliases ###
###############
-
#####################
### functions ####
#####################
-mkdir() { command mkdir -p "$@"; }
-
-
-# fast commit all
-ic() {
- git commit -am "$*"
-}
# file cut copy and paste, like the text buffers :)
cp "$my_f_tempdir"/* "$target"
}
-# history search
-k() { grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | tail -n 40; }
-
-# horizontal row. used to break up output
-hr() { printf "$(tput setaf 5)█$(tput sgr0)%.0s" $(seq $COLUMNS); }
-
-
-# insensitive find
-ifn () {
- find -L . -iname "*$**" 2>/dev/null
-}
-
-# test existence / exists
-te() {
- local ret=0
- for x in "$@"; do
- [[ -e "$x" || -L "$x" ]] || ret=1
- done
- return $ret
-}
# todo, update this
complete -F _longopt la lower low rlt rld rl lld ts ll dircp ex fcp fct fpst gr
-# use sb instead of s is for sudo redirections, eg. sb 'echo "ok fine" > /etc/file'
-sb() {
- local SUDOD="$PWD"
- sudo -i bash -c "$@"
-}
-complete -F _root_command s sb
-
_cdiff-prep() {
# join options which are continued to multiples lines onto one line
_khfix_common() {
local h=${1##*@}
- ssh-keygen -R $h
+ 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
+ ssh-keygen -R $x -f $(readlink -f ~/.ssh/known_hosts)
}
khfix() { # known hosts fix
_khfix_common "$@"
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 .
+ command cp /a/c/repos/bash/!(.git|..|.) ~/.gitconfig .
for x in "$@"; do
tar cz * | ssh $x tar xz
done
done < "$unified"
}
-cgpl ()
+cgpl()
{
- if [[ $# == 0 ]]; then
+ 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/COPYING "$@"
+ 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 "$@"
- command chown -RH "$@"
+ command chown -R "$@"
else
command chown "$@"
fi
return 0
}
+feh() {
+ command feh -FzZ "$@"
+}
funce() {
# like -e for functions. returns on error.
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
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}"
+}
+
gr() {
grep -iIP --color=auto "$@"
}
-
-
-
-
grr() {
if [[ ${#@} == 1 ]]; then
grep -riIP --color=auto "$@" .
fi
}
-
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
if (($linecount > $max_lines)); then
prune_lines=$(($linecount - $max_lines))
head -n $prune_lines "$HISTFILE" >> "$harchive" \
- && sed -ie "1,${prune_lines}d" $HISTFILE
+ && 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
+}
+
+
i() { git "$@"; }
# modified from ~/local/bin/git-completion.bash
# other completion commands are mostly taken from bash_completion package
}
fi
+ic() {
+ # fast commit all
+ git commit -am "$*"
+}
+
+ifn () {
+ # insensitive find
+ find -L . -iname "*$**" 2>/dev/null
+}
if [[ $OS == Windows_NT ]]; then
done
}
-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]}'
+
+k() { # history search
+ grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history} | tail -n 40;
}
-md5diff() {
- [[ $(md5sum < "$1") != $(md5sum < "$2") ]]
+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 /a/opt/Pithosfly/
+ python3 -m pithos&r
+}
pakaraoke() {
# from http://askubuntu.com/questions/456021/remove-vocals-from-mp3-and-get-only-instrumentals
rld /a/h/_site/ li:/var/www/iankelling.org/html
}
+pubip() { curl -4s https://icanhazip.com; }
+whatismyip() { pubip; }
+
+
pwgen() {
- apg -s -m 10 -x 14 -t
+ apg -m 12 -x 16 -t
}
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.
}
-rspicy() { # HOST DOMAIN
+rspicy() { # usage: HOST DOMAIN
+ # connect to spice vm remote host. use vspicy for local host
local port=$(ssh $1<<EOF
sudo virsh dumpxml $2|grep "<graphics.*type='spice'" | \
sed -rn "s/.*port='([0-9]+).*/\1/p"
s() {
# background
- # alias s='SUDOD="$PWD" sudo -i '
- # because this is an alias, and the extra space at the end, it would allow
- # aliases to be used with it. but aliases aren't used in scripts,
- # better to eliminate inconsistencies. Plus, you can't do s=s; $s command
- # with an alias, which I like to do in some functions
- # extra space at the end allows aliases to work
+ # I use a function because otherwise we can't use in a script,
+ # can't assign to variable.
#
# note: gksudo is recommended for X apps because it does not set the
# home directory to the same, and thus apps writing to ~ fuck things up
fi
}
-sdf() {
- c /sdx/test/sandbox/
+
+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
+
ser() {
local s; [[ $EUID != 0 ]] && s=sudo
command srm -ll "$@"
}
+srun() {
+ scp $2 $1:/tmp
+ ssh $1 /tmp/${2##*/} "${@:2}"
+}
+
t() {
local x
local -a args
if type -t trash-put >/dev/null; then
- # skip args that don't exist, or else it's an err
- for x in "$@"; do [[ ! -e $x ]] || args+=("$x"); done
+ # 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 "$@"
}
+te() {
+ # test existence / exists
+ local ret=0
+ for x in "$@"; do
+ [[ -e "$x" || -L "$x" ]] || ret=1
+ done
+ return $ret
+}
+
tm() {
# timer in minutes
(sleep $(calc "$@ * 60") && mpv --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
fi
}
+vc() {
+ [[ $1 ]] || { e "$0: error, expected cmd to run"; return 1; }
+ # manually run vpn so it stays within a network namespace,
+ # until I get it all wired up with systemd.
+ newns vpn start
+ pid=$(< /run/openvpn/client.pid)
+ vpn_on=false
+ if [[ $pid ]]; then
+ if [[ -e /proc/$pid ]]; then
+ vpn_on=true
+ else
+ vpn_on=false
+ s rm -f /run/openvpn/client.pid
+ fi
+ fi
+ $vpn_on || s ip netns exec vpn /usr/sbin/openvpn --daemon ovpn --config /etc/openvpn/client.conf --cd /etc/openvpn --writepid /run/openvpn/client.pid
+ gksudo -- ip netns exec vpn gksudo -u ${SUDO_USER:-$USER} "$@"
+}
+
+transmission() {
+ vc transmission-gtk&
+ i=0
+ while true; do
+ if ((i > 10)); then
+ echo "$0: error: vpn tun0 didn't show up"
+ return 1
+ fi
+ tun_ip=$(s ip netns exec vpn ip a show dev tun0 | sed -rn 's/^ *inet (10\.8\.\S+).*/\1/p')
+ [[ ! $tun_ip ]] || break
+ sleep 1
+ i=$((i + 1))
+ done
+ echo "$0: tun_ip=$tun_ip"
+ [[ $tun_ip ]] || { e "$0: error: no tun0 addr found"; return 1; }
+ ssh dopub bash <<EOF
+set -e
+rule="-A PREROUTING -i eth0 -p tcp -m tcp --dport 63324 -j DNAT --to-destination $tun_ip:63324"
+found=false
+while read -r line; do
+ if [[ \$line == \$rule ]] && ! \$found; then
+ found=true
+ else
+ iptables -t nat -D \${line#-A}
+ fi
+done < <(iptables -t nat -S | grep -E -- '--dport\s+63324')
+\$found || iptables -t nat \$rule
+EOF
+}
+
virshrm() {
for x in "$@"; do virsh destroy "$x"; virsh undefine "$x"; done
}
journalctl --unit=openvpn@client -f -n0
}
+
vpnoff() {
s systemctl stop openvpn@client
}
-vspicy() {
+vspicy() { # usage: VIRSH_DOMAIN
# connect to vms made with virt-install
spicy -p $(sudo virsh dumpxml "$1"|grep "<graphics.*type='spice'"|\
sed -r "s/.*port='([0-9]+).*/\1/")
-
-
###########################################
# stuff that makes sense to be at the end #
###########################################
# 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"
source $HOME/.rvm/scripts/rvm
fi
+
+path_add --end ~/.npm-global
+
# 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