# Copyright 2025 Mitchell Riedstra # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. setaliases() { alias ls="ls -F"; alias ll="ls -lhF"; alias g="grep"; alias m="more"; alias j="jobs"; alias p="pwd"; alias rot13="tr 'A-Za-z' 'N-ZA-Mn-za-m'" alias setxkbmap-list="man xkeyboard-config" # docker-getip $container_id [ -x "$(command -v docker)" ] && \ alias docker-getip="docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'" [ -z "$(command -v gdb)" ] && alias gdb='gdb -q' #shellcheck disable=SC2139 [ -x "$(command -v python3)" ] && alias python="$(command -v python3) -q" if [ "$(uname)" = "Linux" ] ; then alias bc='bc -q' fi } setcoloraliases() { if [ "$(uname)" = "Linux" ] ; then alias ls="ls --color=auto -F"; alias lm='ls -lh --color=force | more'; elif [ "$(uname)" = "FreeBSD" ] ; then alias ls="ls -FG"; alias lm='CLICOLOR_FORCE="1" ls -l | less -r'; fi if echo "color test" | grep -q --color=auto "color test" >/dev/null 2>&1 ; then alias grep="grep --color=auto"; alias egrep='grep -E --color=auto' alias search='grep -E --color=auto -rnI'; fi #shellcheck disable=SC2139 alias diff="$(command -v diff colordiff 2>/dev/null | tail -n 1)"; alias t='tree -CdL' } setsudoaliases() { # Prefer doas if available, as it's likely to be configured by \ # me over sudo _sudo="$(command -v sudo 2>/dev/null | sed 1q)" _doas="$(command -v doas 2>/dev/null | sed 1q)" if [ -n "$_doas" ] ; then _sudo="$_doas" fi _cmds="apt apt-get apt-file apk yum dnf pacman xbps-install xbps-remove pkg_add pkg_delete pkg pkgin tlp tlp-stat zfs zpool btrfs mount umount" # Only add aliases for commands that actually exist on our system if [ -n "$_sudo" ] ; then for _c in $_cmds ; do [ -n "$(command -v "$_c")" ] && \ eval "alias $_c=\"$_sudo $_c\"" done fi case $_sudo in *doas*) alias sudo='doas'; ;; esac } # E.g. after `.kshrc` is called, perhaps in `~/.kshrc.local` # export GOPATH=$HOME/code/gopath # export GOROOT=$HOME/go/1.13.5 # set_go set_go() { export GOPATH="${GOPATH:-$HOME/go}" path_preappend "$GOPATH/bin" GOROOT="${GOROOT:-/usr/local/go}" _gobin="${GOROOT}/bin" path_preappend "$_gobin" } _set_editor() { export EDITOR="$1" export VISUAL="$1" #shellcheck disable=SC2139 alias vi="$EDITOR" #shellcheck disable=SC2139 alias vim="$EDITOR" #shellcheck disable=SC2139 alias edit="$EDITOR" #shellcheck disable=SC2139 alias e="$EDITOR" } set_editor() { for editor in nvim vim vi ed ; do unalias "$editor" >/dev/null 2>&1 e="$(command -v "$editor")" if [ -n "$e" ] && [ -x "$e" ] ; then _set_editor "$e" fi break done } set_pager() { #shellcheck disable=SC2155 export PAGER="$(command -v cat more less 2>/dev/null | tail -n1)" } set_lang() { [ -z "$1" ] && return export CHARSET="$1"; export LANG="$1"; } set_ksh_competion() { if [ -z "$KSH_VERSION" ] ; then return ; fi if [ -r ~/.passsword-store ] ; then #shellcheck disable=SC2046 set -A complete_pass -- show find otp grep \ insert edit generate rm mv cp \ $(showPasswordStore ~/.password-store) #shellcheck disable=SC2046 set -A complete_dpw_1 -- \ show copy type list ls mv cp rm edit otp fnd find insert set -A complete_dpw_2 -- $(dpw list) #shellcheck disable=SC2046 set -A complete_passenv -- \ $(showPasswordStore ~/.password-store) #shellcheck disable=SC2046 set -A complete_dpwenv -- \ $(showPasswordStore ~/.password-store) fi #shellcheck disable=SC2046 set -A complete_ssh -- -L -D -A -X \ $(showsshhosts | awk '{print $1}') #shellcheck disable=SC2046 set -A complete_rsync -- $(showsshhosts | awk '{print $1}') set -A complete_setPrompt -- date time basic } # Usage debugstarttls $ipaddr:$port debugstarttls() { openssl s_client -starttls smtp -crlf -connect "$1" "$2" } randmacgen() { if [ "$(uname)" = "FreeBSD" ] ; then LC_COLLATE=c fi tr -c -d '0123456789abcdef' < /dev/urandom \ | head -c 12 \ | sed 's!^M$!!;s!\-!!g;s!\.!!g;s!\(..\)!\1:!g;s!:$!!' echo "" } # Add a given path to the start of your $PATH if it doesn't already # exist path_preappend() { if [ -z "$1" ] ; then echo "need something to preappend" ; return ; fi pth="$1"; shift if ! echo "$PATH" | grep -qF "$pth" ; then export PATH="$pth:$PATH" fi } path_append() { if [ -z "$1" ] ; then echo "need something to append" ; return ; fi pth="$1"; shift if ! echo "$PATH" | grep -qF "$pth" ; then export PATH="${PATH}:$pth" fi } path_list() { echo "$PATH" | tr ':' '\n' } set_nocaps() { setxkbmap -option ctrl:nocaps setxkbmap -option shift:breaks_caps setxkbmap -option numpad:microsoft } # Usage: dir_oct:file_oct path setperms() { _perm="$1"; shift dir_perms=$(echo "$_perm" | awk -F: '{print $1}') file_perms=$(echo "$_perm" | awk -F: '{print $2}') find "$@" -type f -print0 | xargs -0 chmod "$file_perms" find "$@" -type d -print0 | xargs -0 chmod "$dir_perms" } pwgenForBanks() { set -x pwgen -r '[-#{};[:"'"'"'^()?><.|\/,`=]' -ncsy "$@" set +x } # dump out the exit code of the last process in the from of : # if not zero nzret() { _ret=$? [ -n "${_ret##0}" ] && echo "${_ret}:" } setPrompt() { case $1 in date) export PS1='$(date "+%m.%d %H:%M") `set_my_title``nzret`\$ ' ;; time) export PS1='$(date "+%H:%M") `set_my_title``nzret`\$ ' ;; basic) export PS1='`set_my_title``nzret`\$ ' ;; esac } # Pull a list of all our SSH hostnames out of the config and # dump them to stdout showsshhosts() { cat ~/.ssh/config ~/.ssh/inc/* 2>/dev/null | awk '/^[hH]ost /{$1=""; print $0}' } showPasswordStore() { _passDir="$1" ; shift find "$_passDir" -type f -iname '*.gpg' \ | while read -r _line; do _line="${_line##"$_passDir"}" _line="${_line#/}" _line="${_line%.gpg}" echo "$_line" done unset _passDir } set_title() { printf '\033]0;'"%s"'\007' "$1" } set_my_title() { set_title "$(id -un)@$(hostname 2>/dev/null || cat /etc/hostname 2>/dev/null || cat /etc/myname 2>/dev/null)" } _sys_memory() { ! [ -e "$(command -v vmstat)" ] && return if [ "$(uname)" = "Linux" ] ; then vmstat | tail -n1 | awk '{print $4/1024}' | sed -e's/\..*$//g' elif [ "$(uname)" = "FreeBSD" ] ; then vmstat | tail -n1 | awk '{print $5/1024}' | sed -e's/\..*$//g' elif [ "$(uname)" = "OpenBSD" ] ; then vmstat | sed -n '$p' | awk '{print $4}' | sed 's/M$//' fi } _sys_load() { # Works on BSD too, neat. uptime | sed -E 's/^.*load averages?: ([0-9]+\.[0-9]+).*$/\1/g' } _sys_uptime() { # Took awhile to figure out, but this works on BSD as well uptime | sed -E -e's/^.*up[ ]+//g' -e's/^([^,]*),.*/\1/g' \ -e's/^([^ ]+)[ ]*(.).*/\1\2/g' } timestamp() { date +%m.%d.%y_%H.%M.%S } sshSetAskpass() { export SSH_ASKPASS="$1" export SSH_ASKPASS_REQUIRE=force } # checkSSHAgentForward is useful for if we're an active SSH connection and setup # the `agent_conf` for it. this can be dropped into your ~/.kshrc.local on a # remote server to allow your remote sessions to pick up on forwarded keys, # useful for jump boxes, remote development and similar. checkSSHAgentForward() { if ! [ -d "$HOME"/.ssh ] ; then mkdir -p "$HOME"/.ssh chmod 700 "$HOME"/.ssh fi if [ -z "$SSH_AGENT_PID" ] \ && [ -n "$SSH_CONNECTION" ] \ && [ -n "$SSH_AUTH_SOCK" ] \ && [ -z "$TMUX" ] ; then echo "SSH_AUTH_SOCK=\"$SSH_AUTH_SOCK\"; export SSH_AUTH_SOCK" \ > "$HOME"/.ssh/agent_conf elif [ -t 0 ]; then . "$HOME"/.ssh/agent_conf fi } # checkSSHAgent is my go-to agent setup, it's aggressive, non-standard and a # little hacky, but way more reliable at setting up a persistent ssh-agent than # doing something at login and hoping everything else inherits it # usage is fairly straightforward, drop it into your `~/.kshrc.local` and # let it do it's thing. #shellcheck disable=SC2120 checkSSHAgent() { if [ "$1" = "-k" ] ; then pkill -9 ssh-agent fi # So OpenSSH 10.1 steps on my old configuration, rather than passing in -T # which doesn't exist on older SSH, simply move my configuration out of the # way. if [ -f "$HOME/.ssh/agent" ] ; then rm "$HOME/.ssh/agent" fi ssh_agent_conf="$HOME/.ssh/agent_conf" if [ -e "$ssh_agent_conf" ] ; then #shellcheck disable=SC1090 . "$ssh_agent_conf" fi #shellcheck disable=SC2009 if ! ps aux | awk '{print $2}' | grep -q "$SSH_AGENT_PID" \ || ! [ -e "$ssh_agent_conf" ] \ || [ -z "$SSH_AGENT_PID" ] ; \ then ssh-agent -s | grep -v echo > "$ssh_agent_conf" #shellcheck disable=SC1090 . "$ssh_agent_conf" fi } # checkSSHAgentGPG sets up SSH to talk to GPG for its keys instead checkSSHAgentGPG() { #shellcheck disable=SC2155 export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" } # calls pass and dumps the contents of the password into your environment passenv() { _f="$(mktemp)" pass "$@" > "$_f" #shellcheck disable=SC1090 . "$_f" rm -f "$_f" } # calls dpw ( https://git.riedstra.dev/mitch/dpw ) and dumps the contents of the # password into your environment dpwenv() { _f="$(mktemp)" dpw "$@" > "$_f" #shellcheck disable=SC1090 . "$_f" rm -f "$_f" } # With some minor tweaks, this should work for chromium based browsers too braveListProfiles() { cat ~/.config/BraveSoftware/Brave-Browser/Local\ State \ | jq -r '.profile | .info_cache | to_entries | .[] | "\(.key)\t\(.value.name)"' } # gensubids is useful for generating /etc/subuid and /etc/subgid # if you have say a 3rd user you want to add gensubids() { _step=65536 _err=0 _un= _n= while [ $# -gt 0 ] ; do case $1 in -u) _un="$2"; shift ; shift ;; -n) _n="$2"; shift ; shift ;; *) echo "unknown option: $1"; echo "gensubids -u -n "; return 1 ;; esac ; done if [ -z "$_n" ] ; then echo "need a number" _err=1 fi if [ -z "$_un" ] ; then echo "need a username" _err=1 fi if [ "$_err" -eq 1 ] ; then return 1; fi echo "$_un:$(( (_n*_step) + 1 )):$(( (_n*_step) + _step ))" } # scangit is useful for checking which repositories you've modified scangit() { verbose=false ref="origin/master" while [ $# -gt 0 ] ; do case $1 in -v) verbose=true ; shift ;; -r) ref="$2"; shift ; shift ;; --) break ;; *) echo "bad option '$1' usage: scangit [-v] [-r ] -- " ; return ;; esac ; done find "$@" -iname '.git' -type d 2>/dev/null \ | while read -r _d ; do $verbose && echo "Checking... $(dirname "$_d") against ref \"$ref\"" cd "$(dirname "$_d")" if $verbose ; then git diff-index --quiet "$ref" 2>/dev/null \ || echo "Has changes" else git diff-index --quiet "$ref" 2>/dev/null \ || echo "$(dirname "$_d")" fi cd - >/dev/null done } gitdate() { date="" while [ $# -gt 0 ] ; do case $1 in -d) date="$2" ; shift ; shift ;; *) printf "Bad option: $1... usage:\n$0 -d \"\$date_string\"\n" ; return ;; esac ; done date="$(date --date "$date")" export GIT_AUTHOR_DATE="$date" export GIT_COMMITTER_DATE="$date" echo export GIT_AUTHOR_DATE="$date" echo export GIT_COMMITTER_DATE="$date" } gitdateUnset() { unset GIT_AUTHOR_DATE unset GIT_COMMITTER_DATE } gpgTmpDir() { __privdir='/dev/shm' if [ "$(uname)" != "Linux" ] ; then echo "Warning /tmp may not be a ramdisk" __privdir="/tmp" fi set -x if echo "$GNUPGHOME" | grep -q "$__privdir"; then rm -rvf "$GNUPGHOME" fi #shellcheck disable=SC2155 export GNUPGHOME="$(mktemp -d "$__privdir"/GPG.XXXXXX)" set +x } setcolorterminal() { case $TERM in xterm*) export TERM=xterm-256color ;; screen*) export TERM=screen-256color ;; esac } setlscolors() { if [ "$(uname)" = "Linux" ] ; then export LS_COLORS='di=36;40:ln=1;31;40:so=32;40:pi=33;40:ex=1;32;40:bd=34;46:cd=34;43:su=0;41:sg=0;46:tw=0;42:ow=0;43:' elif [ "$(uname)" = "FreeBSD" ] ; then export LSCOLORS='gxBxcxdxCxegedabagacad' fi } colormanpages() { export LESS_TERMCAP_mb="" export LESS_TERMCAP_md="" export LESS_TERMCAP_me="" export LESS_TERMCAP_se="" export LESS_TERMCAP_so="" export LESS_TERMCAP_ue="" export LESS_TERMCAP_us="" ## Gentoo is nuts export GROFF_NO_SGR=1 } pkg_switch_branch() { _f="/etc/pkg/FreeBSD.conf" cp $_f ${_f}.orig sed -e's/quarterly/latest/' < ${_f}.orig > ${_f} } SHELL_CONFIG=".kshrc" COLOR=0 case "$TERM" in xterm*) COLOR=1;; *256color) COLOR=1;; esac path_preappend "$HOME/bin" PRELOAD="$HOME/${SHELL_CONFIG}.pre" LOCAL="$HOME/${SHELL_CONFIG}.local" # Don't put any variables below this, as they can't be overridden before the # functions if you do that # Load pre config [ -r "$PRELOAD" ] && . "$PRELOAD" set_pager # note that the use of set_editor and _set_editor on oksh may # change the input mode. ( set -o emacs ) after to go back set_editor # Also, opinionated, hope you like vim/vi setaliases setsudoaliases # Support various different shells if [ -n "$YASH_VERSION" ] ; then echo "Intentionally left blank" >/dev/null 2>&1 elif [ -n "$KSH_VERSION" ] ; then HISTFILE="$HOME/.ksh_history" HISTSIZE=10000 bind ^L=clear-screen set -o emacs set_ksh_competion # if you want PWD # export PS1='`nzret`\u@\h \$PWD \$ ' export PS1='`set_my_title``nzret`\u@\h\$ ' if [ "$(id -u)" -eq 0 ] ; then export PS1='`set_my_title``nzret`\h\$ ' fi elif [ "$SHELL" = "/bin/sh" ] && [ "$(uname)" = "FreeBSD" ] ; then set -o emacs #shellcheck disable=SC2155 export PS1="$(whoami)"'@\h:\w \$ ' elif [ -n "$BASH" ] ; then HISTFILE="$HOME/.bash_history" HISTSIZE=10000 HISTFILESIZE=10000 shopt -s histappend export PROMPT_COMMAND="history -a; history -c; history -r" # if you want PWD # export PS1='\u@\h \$PWD \$ ' export PS1='\u@\h\$ ' if [ "$(id -u)" -eq 0 ] ; then export PS1='\h\$ ' fi fi setcolor() { colormanpages setcolorterminal setcoloraliases setlscolors } [ -d "$HOME/.local/bin" ] && path_preappend "$HOME/.local/bin" # Include local configuration options [ -r "$LOCAL" ] && . "$LOCAL"