devinteske

My .bash_profile

May 29th, 2018 (edited)
4,755
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 83.46 KB | None | 0 0
  1. # -*- tab-width:  4 -*- ;; Emacs
  2. # vi: set tabstop=8     :: Vi/ViM
  3. #
  4. # .bash_profile
  5. #   Author:      Devin Teske <[email protected]>
  6. #   Last Change: 2026 Sep 30
  7. #
  8. ############################################################ GLOBALS
  9.  
  10. #
  11. # Global exit status variables
  12. #
  13. export SUCCESS=0
  14. export FAILURE=1
  15.  
  16. #
  17. # Are we running interactively?
  18. #
  19. interactive=
  20. case "$-" in
  21. *i*) interactive=1
  22. esac
  23.  
  24. #
  25. # Is filename globbing enabled?
  26. #
  27. if [ "$ZSH_NAME" ]; then
  28.     glob=
  29.     setopt shwordsplit
  30. else
  31.     glob=1
  32.     case "$SHELLOPTS" in noglob|*:noglob:*|*:noglob) glob= ;; esac
  33. fi
  34.  
  35. #
  36. # OS Specifics
  37. # NB: Requires uname(1) -- from base system
  38. #
  39. : ${UNAME_s:=$(uname -s)}
  40. : ${UNAME_r:=$(uname -r)}
  41. : ${UNAME_p:=$(uname -p)}
  42. : ${MESSAGES:=/var/log/messages}
  43. case "$UNAME_s" in
  44. Linux) Linux=$( lsb_release -si 2> /dev/null ) ;;
  45. esac
  46.  
  47. #
  48. # Fix lolcat to work properly in local XTerm
  49. #
  50. [ "$TERM" != "${TERM#xterm}" -a ! "$SSH_CLIENT" ] && stty tab0
  51.  
  52. #
  53. # bash(1) builtin's we should pass to $LOLCAT [lolcat]
  54. #
  55. LOL_BUILTINS='cd dirs echo help popd printf pushd pwd shopt times type'
  56. _LOL_BUILTINS=
  57. [ "$glob" ] && set -f
  58. for _prog in $LOL_BUILTINS; do
  59.     _LOL_BUILTINS="$_LOL_BUILTINS|$_prog"
  60. done
  61. unset _prog
  62. _LOL_BUILTINS="${_LOL_BUILTINS#|}"
  63. [ "$glob" ] && set +f
  64.  
  65. #
  66. # External programs we should NOT pass to $LOLCAT [lolcat]
  67. #
  68. NOLOL_PROGS='
  69.     adduser arc
  70.     *bash bashbug bc bitchx bsdconfig bsddialog bsdinstall bsdpv
  71.     claude cmatrix condy cscope csh cvsbug
  72.     dd dialog dpv
  73.     edit edquota ee emacs* env etcupdate ex
  74.     freebsd-update fsdb *ftp fvwm-bug
  75.     *gdb*
  76.     *hx
  77.     iftop irssi
  78.     *key *keys
  79.     lldb *login lolcat ls
  80.     Mail mail* *man* mping
  81.     nano ngctl nvi
  82.     perlbug perlthanks pico pppctl
  83.     rcp *run
  84.     sade *scp screen sh shgid sr srcpv srvi *ssh* su sudo* sysinstall
  85.         systat
  86.     talk tcsh *telnet tmux top tzsetup
  87.     vi *view vigr *vim* vipw visudo
  88.     watch
  89.     zsh
  90. ' # NOLOL_PROGS
  91. _NOLOL_PROGS=
  92. [ "$glob" ] && set -f
  93. for _prog in $NOLOL_PROGS; do
  94.     _NOLOL_PROGS="$_NOLOL_PROGS|$_prog"
  95. done
  96. unset _prog
  97. _NOLOL_PROGS="${_NOLOL_PROGS#|}"
  98. [ "$glob" ] && set +f
  99.  
  100. #
  101. # Commands we should pass to $LOLCAT [lolcat]
  102. #
  103. LOL_CMDS='
  104.     # One case pattern per-line; no inline comments
  105.     # NB: Whitespace needs to be escaped or quoted
  106.     # NB: Patterns implicitly allow trailing args
  107.  
  108.     # FreeBSD commands
  109.     "wpa_cli [a-z]*"
  110.  
  111.     # FreeBSD pkg(8) commands
  112.     "pkg annotate -y"
  113.     "pkg annotate "*" -y"
  114.     "pkg annotate --yes"
  115.     "pkg annotate "*" --yes"
  116.     "pkg autoremove -y"
  117.     "pkg autoremove "*" -y"
  118.     "pkg autoremove --yes"
  119.     "pkg autoremove "*" --yes"
  120.     "pkg check -y"
  121.     "pkg check "*" -y"
  122.     "pkg check --yes"
  123.     "pkg check "*" --yes"
  124.     "pkg clean -y"
  125.     "pkg clean "*" -y"
  126.     "pkg clean --yes"
  127.     "pkg clean "*" --yes"
  128.     "pkg delete -y"
  129.     "pkg delete "*" -y"
  130.     "pkg delete --yes"
  131.     "pkg delete "*" --yes"
  132.     "pkg fetch -y"
  133.     "pkg fetch "*" -y"
  134.     "pkg fetch --yes"
  135.     "pkg fetch "*" --yes"
  136.     "pkg install -y"
  137.     "pkg install "*" -y"
  138.     "pkg install --yes"
  139.     "pkg install "*" --yes"
  140.     "pkg lock -y"
  141.     "pkg lock "*" -y"
  142.     "pkg lock --yes"
  143.     "pkg lock "*" --yes"
  144.     "pkg remove -y"
  145.     "pkg remove "*" -y"
  146.     "pkg remove --yes"
  147.     "pkg remove "*" --yes"
  148.     "pkg unlock -y"
  149.     "pkg unlock "*" -y"
  150.     "pkg unlock --yes"
  151.     "pkg unlock "*" --yes"
  152.     "pkg upgrade -y"
  153.     "pkg upgrade "*" -y"
  154.     "pkg upgrade --yes"
  155.     "pkg upgrade "*" --yes"
  156.  
  157.     # VCS commands
  158.     "cvs ci -m"
  159.     "cvs ci "*" -m"
  160.     "cvs commit -m"
  161.     "cvs commit "*" -m"
  162.     "git commit -m"
  163.     "git commit "*" -m"
  164.     "git commit --message"
  165.     "git commit "*" --message"
  166.     "git commit --no-edit"
  167.     "git commit "*" --no-edit"
  168.     "git revert --no-edit"
  169.     "git revert "*" --no-edit"
  170.     "p4 branch -"[dio]
  171.     "p4 branch "*" -"[dio]
  172.     "p4 change -"[dio]
  173.     "p4 change "*" -"[dio]
  174.     "p4 changelist -"[dio]
  175.     "p4 changelist "*" -"[dio]
  176.     "p4 client -"[dio]
  177.     "p4 client "*" -"[dio]
  178.     "p4 depot -"[dio]
  179.     "p4 depot "*" -"[dio]
  180.     "p4 job -"[dio]
  181.     "p4 job "*" -"[dio]
  182.     "p4 label -"[dio]
  183.     "p4 label "*" -"[dio]
  184.     "p4 protect -"[io]
  185.     "p4 protect "*" -"[io]
  186.     "p4 resolve -a"[mty]
  187.     "p4 resolve "*" -a"[mty]
  188.     "p4 stream -"[dio]
  189.     "p4 stream "*" -"[dio]
  190.     "p4 submit -"[di]
  191.     "p4 submit "*" -"[di]
  192.     "p4 user -"[dio]
  193.     "p4 user "*" -"[dio]
  194.     "p4 workspace -"[dio]
  195.     "p4 workspace "*" -"[dio]
  196.     "svn ci -m"
  197.     "svn ci "*" -m"
  198.     "svn ci --message"
  199.     "svn ci "*" --message"
  200.     "svn ci --non-interactive"
  201.     "svn ci "*" --non-interactive"
  202.     "svn commit -m"
  203.     "svn commit "*" -m"
  204.     "svn commit --message"
  205.     "svn commit "*" --message"
  206.     "svn commit --non-interactive"
  207.     "svn ci "*" --non-interactive"
  208.     "svnlite ci -m"
  209.     "svnlite ci "*" -m"
  210.     "svnlite ci --message"
  211.     "svnlite ci "*" --message"
  212.     "svnlite ci --non-interactive"
  213.     "svnlite ci "*" --non-interactive"
  214.     "svnlite commit -m"
  215.     "svnlite commit "*" -m"
  216.     "svnlite commit --message"
  217.     "svnlite commit "*" --message"
  218.     "svnlite commit --non-interactive"
  219.     "svnlite ci "*" --non-interactive"
  220.  
  221. ' # LOL_CMDS
  222. _LOL_CMDS=$( echo "$LOL_CMDS" |
  223.     while read -r _cmd; do
  224.         [ "${_cmd:-x}" = "${_cmd#\#}" ] || continue
  225.         echo -n "|$_cmd|$_cmd\[\$IFS]*"
  226.     done
  227. )
  228. _LOL_CMDS="${_LOL_CMDS#|}"
  229.  
  230. #
  231. # Commands we should NOT pass to $LOLCAT [lolcat]
  232. #
  233. NOLOL_CMDS='
  234.     # One case pattern per-line; no inline comments
  235.     # NB: Whitespace needs to be escaped or quoted
  236.     # NB: Patterns implicitly allow trailing args
  237.  
  238.     # Commands containing pipe
  239.     *"|"*
  240.  
  241.     # General commands that launch $EDITOR or behave interactively
  242.     "crontab -e"
  243.     "crontab "*" -e"
  244.     "sdiff -o"
  245.     "sdiff "*" -o"
  246.  
  247.     # FreeBSD specific commands that launch $EDITOR or behave interactively
  248.     "bsdlabel -e"
  249.     "camcontrol modepage "*" -e"
  250.     "disklabel -e"
  251.     "gbde init "*" -i"
  252.     "gvinum create"
  253.     "make config"
  254.     "make import"
  255.     "wpa_cli"
  256.  
  257.     # FreeBSD pkg(8) commands that either prompt or show progress
  258.     "pkg annotate"
  259.     "pkg autoremove"
  260.     "pkg check"
  261.     "pkg clean"
  262.     "pkg delete"
  263.     "pkg fetch"
  264.     "pkg install"
  265.     "pkg lock"
  266.     "pkg remove"
  267.     "pkg shell"
  268.     "pkg unlock"
  269.     "pkg upgrade"
  270.  
  271.     # VCS commands that launch $EDITOR or behave interactively
  272.     "cvs ci"
  273.     "cvs commit"
  274.     "git commit"
  275.     "git commit --amend"
  276.     "git commit"*"--amend"
  277.     "git commit --amen"
  278.     "git commit"*"--amen"
  279.     "git commit --am"
  280.     "git commit"*"--am"
  281.     "git arc create "*
  282.     "git arc stage "*
  283.     "git arc update "*
  284.     "git help"
  285.     "git rebase -i"
  286.     "git rebase -i "*
  287.     "git rebase "*" -i"
  288.     "git rebase --interactive"
  289.     "git rebase "*" --interactive"
  290.     "git revert"
  291.     "p4 attribute -i"
  292.     "p4 attribute "*" -i"
  293.     "p4 branch"
  294.     "p4 change"
  295.     "p4 changelist"
  296.     "p4 client"
  297.     "p4 depot"
  298.     "p4 job"
  299.     "p4 label"
  300.     "p4 login"
  301.     "p4 passwd"
  302.     "p4 protect"
  303.     "p4 resolve"
  304.     "p4 stream"
  305.     "p4 submit"
  306.     "p4 user"
  307.     "p4 workspace"
  308.     "svn ci"
  309.     "svn commit"
  310.     "svnlite ci"
  311.     "svnlite commit"
  312.  
  313.     # Other commands that behave interactively
  314.     "loadkeys"
  315.     "loadkeys "*
  316.     "make chroot_shell"
  317.     "make "*" chroot_shell"
  318.     "make distclean"
  319.     "make "*" distclean"
  320.     "make remove_chroot"
  321.     "make "*" remove_chroot"
  322.  
  323. ' # NOLOL_CMDS
  324. _NOLOL_CMDS=$( echo "$NOLOL_CMDS" |
  325.     while read -r _cmd; do
  326.         [ "${_cmd:-x}" = "${_cmd#\#}" ] || continue
  327.         echo -n "|$_cmd|$_cmd\[\$IFS]*"
  328.     done
  329. )
  330. _NOLOL_CMDS="${_NOLOL_CMDS#|}"
  331.  
  332. #
  333. # Where are apache's log files?
  334. #
  335. case "$UNAME_s" in
  336. FreeBSD)
  337.     case "$UNAME_r" in
  338.     4.8-*)
  339.         : ${APACHE_ERROR_LOG:=/usr/local/www/logs/error_log}
  340.         : ${APACHE_ACCESS_LOG:=/usr/local/www/logs/access_log}
  341.         : ${APACHE_ERROR_LOG_SA:=$APACHE_ERROR_LOG}
  342.         : ${APACHE_ACCESS_LOG_SA:=$APACHE_ACCESS_LOG}
  343.         : ${APACHE_SSL_ERROR_LOG:=/usr/local/www/logs/ssl_error_log}
  344.         : ${APACHE_SSL_ACCESS_LOG:=/usr/local/www/logs/ssl_access_log}
  345.         ;;
  346.     8.3-*)
  347.         : ${APACHE_ERROR_LOG:=/var/log/httpd-error.log}
  348.         : ${APACHE_ACCESS_LOG:=/var/log/httpd-access.log}
  349.         : ${APACHE_ERROR_LOG_SA:=$APACHE_ERROR_LOG}
  350.         : ${APACHE_ACCESS_LOG_SA:=$APACHE_ACCESS_LOG}
  351.         : ${APACHE_SSL_ERROR_LOG:=/var/log/httpd-ssl_error.log}
  352.         : ${APACHE_SSL_ACCESS_LOG:=/var/log/httpd-ssl_request.log}
  353.         ;;
  354.     *)
  355.         : ${APACHE_ERROR_LOG:=/usr/local/apache2/logs/error_log}
  356.         : ${APACHE_ACCESS_LOG:=/usr/local/apache2/logs/access_log}
  357.         : ${APACHE_ERROR_LOG_SA:=$APACHE_ERROR_LOG}
  358.         : ${APACHE_ACCESS_LOG_SA:=$APACHE_ACCESS_LOG}
  359.         : ${APACHE_SSL_ERROR_LOG:=/usr/local/apache2/logs/ssl_error_log}
  360.         : ${APACHE_SSL_ACCESS_LOG:=/usr/local/apache2/logs/ssl_access_log}
  361.         ;;
  362.     esac
  363.     ;;
  364. Linux)
  365.     case "$Linux" in
  366.     Ubuntu)
  367.         etc_httpd=/etc/apache2
  368.         error_log=error.log access_log=access.log
  369.         internal_error_log=internal_error_log
  370.         internal_access_log=internal_access_log
  371.         ssl_error_log=ssl_error_log
  372.         ssl_access_log=ssl_access_log
  373.         ;;
  374.     CentOS)
  375.         etc_httpd=/etc/httpd
  376.         error_log=error_log access_log=access_log
  377.         internal_error_log=internal_error_log
  378.         internal_access_log=internal_access_log
  379.         ssl_error_log=ssl_error_log
  380.         ssl_access_log=ssl_access_log
  381.         ;;
  382.     *)
  383.         etc_httpd=/etc/httpd
  384.         [ -d "$etc_httpd" ] || etc_httpd=/etc/apache2
  385.         error_log=error_log access_log=access_log
  386.         internal_error_log=internal_error_log
  387.         internal_access_log=internal_access_log
  388.         ssl_error_log=ssl_error_log
  389.         ssl_access_log=ssl_access_log
  390.     esac
  391.     : ${APACHE_ERROR_LOG:=$etc_httpd/logs/$error_log}
  392.     : ${APACHE_ACCESS_LOG:=$etc_httpd/logs/$access_log}
  393.     : ${APACHE_ERROR_LOG_SA:=$etc_httpd/logs/$internal_error_log}
  394.     : ${APACHE_ACCESS_LOG_SA:=$etc_httpd/logs/$internal_access_log}
  395.     : ${APACHE_SSL_ERROR_LOG:=$etc_httpd/logs/$ssl_error_log}
  396.     : ${APACHE_SSL_ACCESS_LOG:=$etc_httpd/logs/$ssl_access_log}
  397.     ;;
  398. CYGWIN*)
  399.     : ${APACHE_ERROR_LOG:=/var/log/apache2/error_log}
  400.     : ${APACHE_ACCESS_LOG:=/var/log/apache2/access_log}
  401.     : ${APACHE_ERROR_LOG_SA:=$APACHE_ERROR_LOG}
  402.     : ${APACHE_ACCESS_LOG_SA:=$APACHE_ACCESS_LOG}
  403.     : ${APACHE_SSL_ERROR_LOG:=/var/log/apache2/ssl_error_log}
  404.     : ${APACHE_SSL_ACCESS_LOG:=/var/log/apache2/ssl_access_log}
  405.     ;;
  406. esac
  407.  
  408. #
  409. # Set DISPLAY for Xming/XQuartz
  410. #
  411. case "$UNAME_s" in
  412. Darwin*)
  413.     export DISPLAY=:0.0
  414.     ;;
  415. CYGWIN*)
  416.     export DISPLAY=localhost:0
  417.     ;;
  418. esac
  419.  
  420. #
  421. # For dialog(1), bsddialog(1), and Xdialog(1) menus
  422. # NB: cvspicker and ssh-agent-dup in FUNCTIONS below
  423. #
  424. DIALOG_MENU_TAGS="123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  425.  
  426. #
  427. # Default directory to store dialog(1), bsddialog(1), and Xdialog(1) temp files
  428. #
  429. : ${DIALOG_TMPDIR:="/tmp"}
  430.  
  431. #
  432. # cvspicker export commands (one per-line)
  433. #
  434. CVSPICKER_EXPORTS="
  435.     CVS_RSH=ssh CVSROOT=cvs.vicor.com:/repos/projects
  436.     CVS_RSH=ssh CVSROOT=mp1.yvod.com:/CVSbase/iPhoneApps
  437.     CVS_RSH=ssh CVSROOT=:ext:[email protected]:/cvsroot/druidbsd
  438.     CVS_RSH=ssh CVSROOT=dcvs.freebsd.org:/home/dcvs
  439.     CVS_RSH=ssh CVSROOT=pcvs.freebsd.org:/home/pcvs
  440.     CVS_RSH=ssh CVSROOT=projcvs.freebsd.org:/home/projcvs
  441.     CVS_RSH=ssh CVSROOT=ncvs.freebsd.org:/home/ncvs
  442. " # END-QUOTE
  443.  
  444. #
  445. # perforce settings
  446. #
  447. export P4CONFIG=P4CONFIG
  448.  
  449. #
  450. # route(8) helper settings (see routes() et al., in FUNCTIONS)
  451. #
  452. # NB: ROUTES_${NAME} syntax is "DOMAIN ROUTE_ARGS" where:
  453. #   NAME        1st arg to routes() (converted to upper-case)
  454. #   DOMAIN      Domain prefix to match in hosts(5)
  455. #   ROUTE_ARGS  Arguments to pass to route(8) for matched entries
  456. #
  457. case "$UNAME_s" in
  458. FreeBSD)
  459.     pptp_iface=$( service pptp iface 2> /dev/null )
  460.     ROUTES_PANZURA=".pixel8networks.com -iface ${pptp_iface:-tun0}"
  461.     unset pptp_iface
  462.     ;;
  463. *) ROUTES_PANZURA=".pixel8networks.com -iface ppp0"
  464. esac
  465. ROUTES_VICOR=".vicor.com 10.242.182.1"
  466.  
  467. ############################################################ FUNCTIONS
  468.  
  469. unalias quietly 2> /dev/null
  470. quietly() { "$@" > /dev/null 2>&1; }
  471.  
  472. quietly unalias have
  473. have() { type "$@" > /dev/null 2>&1; }
  474.  
  475. quietly unalias eval2
  476. eval2() {
  477.     if [ "$LOLCAT" ]; then
  478.         echo "$*" | $LOLCAT
  479.     else
  480.         echo "$*"
  481.     fi
  482.     eval "$@"
  483. }
  484.  
  485. quietly unalias spool
  486. spool()
  487. {
  488.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  489.     local path="$( which qmon )"
  490.     if [ ! "$path" ]; then
  491.         echo "$FUNCNAME: qmon not installed" >&2
  492.         return $FAILURE
  493.     fi
  494.     eval2 cd "${path%/bin/*}/default/spool"
  495. }
  496.  
  497. # setvar $var_to_set [$value]
  498. #
  499. # Implement setvar for shells unlike FreeBSD sh(1).
  500. #
  501. if ! have setvar; then
  502. setvar()
  503. {
  504.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  505.     [ $# -gt 0 ] || return ${SUCCESS:-0}
  506.     local __setvar_var_to_set="$1" __setvar_right="$2" __setvar_left=
  507.     case $# in
  508.     1) unset "$__setvar_var_to_set"
  509.        return $? ;;
  510.     2) : fall through ;;
  511.     *) echo "$FUNCNAME: too many arguments" >&2
  512.        return ${FAILURE:-1}
  513.     esac
  514.     case "$__setvar_var_to_set" in *[!0-9A-Za-z_]*)
  515.         echo "$FUNCNAME: $__setvar_var_to_set: bad variable name" >&2
  516.         return 2
  517.     esac
  518.     while case "$__setvar_r" in *\'*) : ;; *) false ; esac
  519.     do
  520.         __setvar_left="$__setvar_left${__setvar_right%%\'*}'\\''"
  521.         __setvar_right="${__setvar_right#*\'}"
  522.     done
  523.     __setvar_left="$__setvar_left${__setvar_right#*\'}"
  524.     eval "$__setvar_var_to_set='$__setvar_left'"
  525. }
  526. fi
  527.  
  528. # lolexec [$command [$args ...]]
  529. #
  530. # Create a wrapper function for $command, sending output to `lolcat' (or
  531. # `cowsay') transparently. To make this execute for all commands, automatically
  532. # sending all output to lolcat, make this function the DEBUG trap.
  533. #
  534. # For example:
  535. #   trap lolexec DEBUG
  536. #
  537. # When trapped as the DEBUG routine in bash, any/all command lines that...
  538. #   + Do NOT contain the pipe character
  539. #   + Do NOT start with an exclamation point by-itself (e.g., "! top")
  540. # ... will have their output sent to lolcat.
  541. #
  542. # NB: Requires awk(1) -- from base system
  543. #
  544. if [ "$ZSH_NAME" ]; then
  545.     preexec() { lolexec "$1"; }
  546.     precmd() { trap - DEBUG; }
  547.     type_t() {
  548.         case "$( builtin type "$@" 2> /dev/null )" in
  549.         *" is a shell function") builtin echo function ;;
  550.         *" is an alias for "*) builtin echo alias ;;
  551.         *" is a shell builtin") builtin echo builtin ;;
  552.         *" is a reserved word") builtin echo keyword ;;
  553.         *" is /"*) builtin echo file ;;
  554.         *) builtin echo unknown
  555.         esac
  556.     }
  557. else
  558.     type_t() { builtin type -t "$@" 2> /dev/null; }
  559.     LOLEXEC='[ "$( trap -p DEBUG )" ]'
  560.     LOLEXEC="$LOLEXEC || trap \"trap - DEBUG; lolexec\" DEBUG"
  561. fi
  562. alias -- +lol='trap - DEBUG; +lolcat'
  563. alias -- -lol='-lolcat'
  564. quietly unalias -lolcat
  565. -lolcat()
  566. {
  567.     if [ $# -lt 1 -o ! "$*" ]; then
  568.         unset PROMPT_COMMAND
  569.         return $SUCCESS
  570.     fi
  571.  
  572.     local cmd
  573.     for cmd in "$@"; do
  574.         _NOLOL_CMDS="$_NOLOL_CMDS|$cmd|$cmd\[\$IFS]*"
  575.     done
  576. }
  577. case "$UNAME_s" in
  578. Darwin) -lol ls ;;
  579. esac
  580. quietly unalias +lolcat
  581. +lolcat()
  582. {
  583.     PROMPT_COMMAND="$LOLEXEC"
  584.     LOLCAT="${*:-$LOLCAT}"
  585. }
  586. quietly unalias lolexec
  587. lolexec()
  588. {
  589.     builtin [ "$ZSH_NAME" ] && builtin local FUNCNAME="$funcstack[1]"
  590.     builtin export OLDPWD # Required for `cd -' and `pushd -'
  591.     builtin local _lolcat="$LOLCAT" _lc=
  592.     builtin local _prog _register=1
  593.     builtin local cmd fprog prefix=_${FUNCNAME}_ prog=
  594.     case "$_LOLFUNC" in
  595.     ""|$FUNCNAME) builtin : fall through ;;
  596.     *)
  597.         builtin unset -f $_LOLFUNC 2> /dev/null
  598.         type_t $prefix$_LOLFUNC > /dev/null 2>&1 &&
  599.             builtin eval "$( builtin type $prefix$_LOLFUNC |
  600.                 builtin command awk -v prefix=$prefix '
  601.                     NR == 2 { sub("^" prefix, ""); print }
  602.                     NR > 2
  603.             ' )"
  604.     esac
  605.     _LOLFUNC=
  606.     case "$_lolcat" in
  607.     "") builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  608.         builtin return ;;
  609.     *lolcat) _lc=1 ;;
  610.     esac
  611.     if builtin [ "$ZSH_NAME" ]; then
  612.         cmd="$1"
  613.     else
  614.         case "$#" in
  615.         0) cmd=$( history 1 ) || builtin return
  616.            cmd="${cmd#*[0-9]  }" ;;
  617.         *) cmd="$*"
  618.         esac
  619.     fi
  620.     builtin [ "$cmd" ] || builtin return
  621.     builtin export LOL_CMD="$cmd"
  622.     builtin eval "case \"\$cmd\" in
  623.     $_LOL_CMDS) builtin : fall through ;;
  624.     $_NOLOL_CMDS)
  625.         builtin [ \$# -eq 0 ] || builtin [ \"\$ZSH_NAME\" ] || \"\$@\"
  626.         builtin return
  627.     esac"
  628.     for prog in $cmd; do
  629.         builtin [ "$prog" = "!" ] || builtin break
  630.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  631.         builtin return
  632.     done
  633.     case "$prog" in
  634.     ""|*[^[:alnum:]_]*)
  635.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  636.         builtin return
  637.     esac
  638.     _prog=$prog
  639.     while builtin [ "$( type_t $prog 2> /dev/null )" = alias ]; do
  640.         fprog=$( builtin type $prog )
  641.         fprog="${fprog#*\`}"
  642.         fprog="${fprog%\'}"
  643.         for prog in $fprog; do
  644.             builtin [ "$prog" = "!" ] || builtin break
  645.             builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  646.             builtin return
  647.         done
  648.         builtin [ "$prog" = "$_prog" ] && builtin break # infinite loop
  649.         _prog=$prog
  650.     done
  651.     if builtin [ "$prog" = "$FUNCNAME" -o ! "${prog#type_t}" ]; then
  652.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  653.         builtin return
  654.     fi
  655.     case "$( type_t $prog 2> /dev/null )" in
  656.     alias|file) # blacklist
  657.         builtin eval "case \"\$prog\" in
  658.         $_NOLOL_PROGS)
  659.             builtin [ \$# -eq 0 ] || builtin [ \"\$ZSH_NAME\" ] ||
  660.                 \"\$@\"
  661.             builtin return
  662.         esac"
  663.         fprog="builtin command $prog"
  664.         _LOLFUNC=$prog
  665.         builtin [ "$_lc" ] && case "$prog" in
  666.         *less|*more) # [bz,lz,xz,z]less [z]more
  667.             builtin eval "function $prog()
  668.             {
  669.                 $fprog \"\$@\" | $LOLCAT -f |
  670.                     builtin command less -R
  671.             }"
  672.             _register= ;;
  673.         ping*) # l2ping ping ping6
  674.             _lolcat="$_lolcat -a" ;;
  675.         tail) # check for `-f' or `-F'
  676.             case "$cmd" in
  677.             *[$IFS]-[fF]|*[$IFS]-[fF][$IFS]*) _lolcat="$_lolcat -a"
  678.             esac ;;
  679.         esac
  680.         ;;
  681.     builtin|keyword) # whitelist
  682.         builtin eval "case \"\$prog\" in
  683.         $_LOL_BUILTINS) builtin : fall through ;;
  684.         *)
  685.             builtin [ \$# -eq 0 ] || builtin [ \"\$ZSH_NAME\" ] ||
  686.                 \"\$@\"
  687.             builtin return
  688.         esac"
  689.         fprog="builtin $prog"
  690.         _LOLFUNC=$prog ;;
  691.     function) # overlay
  692.         builtin [ "$_lc" ] && case "$prog" in
  693.         tlog|tm|taal|tael) # wrappers to `tail -F'
  694.             _lolcat="$_lolcat -a" ;;
  695.         esac
  696.         builtin eval "$prefix$( builtin type $prog |
  697.             builtin command awk 'NR>1' )"
  698.         fprog="$prefix$prog"
  699.         _LOLFUNC=$prog ;;
  700.     *) # unknown
  701.         builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  702.         builtin return
  703.     esac
  704.     builtin [ "$LOLDEBUG" ] && builtin echo \
  705.         "$FUNCNAME: prog=[$prog] fprog=[$fprog] cmd=[$cmd]" >&2
  706.     builtin [ "$_register" ] && builtin eval "function $prog()
  707.     {
  708.         exec 3>&1
  709.         local cwd=\"\${D0:-\${DIRSTACK[0]:-\$( builtin pwd )}}\"
  710.         builtin local meta=\"\$( exec 4>&1; (
  711.             $fprog \"\$@\"
  712.             builtin echo \"\$?:\$( builtin pwd )\" >&4
  713.         ) | $_lolcat >&3 )\"
  714.         builtin local ret=\"\${meta%%:*}\" chdir=\"\${meta#*:}\"
  715.         case \"$prog\" in
  716.         dirstack_wrap) builtin \"\$@\" ;;
  717.         pushd|popd) builtin $prog \"\$@\" ;;
  718.         *) builtin [ \"\$cwd\" != \"\$chdir\" ] &&
  719.             builtin cd \"\$chdir\"
  720.         esac > /dev/null 2>&1
  721.         builtin type dirstack2d > /dev/null 2>&1 &&
  722.             builtin [ \"\$cwd\" != \"\$chdir\" ] && dirstack2d
  723.         builtin return \$ret
  724.     }"
  725.     builtin [ $# -eq 0 ] || builtin [ "$ZSH_NAME" ] || "$@"
  726. }
  727.  
  728. if have cowsay; then
  729. # cowsay
  730. #
  731. # Default arguments for cowsay
  732. #
  733. cowsay()
  734. {
  735.     local wrap=-n
  736.     [ $# -gt 0 ] && wrap="-W $(( ${COLUMNS:-80} - 3 ))"
  737.     command cowsay $wrap "$@"
  738. }
  739.  
  740. # unicornsay
  741. #
  742. # Cows are boring
  743. #
  744. # NB: unicorn.cow obtained from https://github.com/schacon/cowsay/pull/13
  745. # Special Thanks to: Sven Wittevrongel (@CupOfTea696)
  746. #
  747. unicornsay()
  748. {
  749.     local wrap=-n
  750.     [ $# -gt 0 ] && wrap="-W $(( ${COLUMNS:-80} - 3 ))"
  751.     command cowsay -f ~/bin/unicorn.cow $wrap "$@"
  752. }
  753. fi # have cowsay
  754.  
  755. if have cowthink; then
  756. # cowthink
  757. #
  758. # Default arguments for cowthink
  759. #
  760. cowthink()
  761. {
  762.     local wrap=-n
  763.     [ $# -gt 0 ] && wrap="-W $(( ${COLUMNS:-80} - 3 ))"
  764.     command cowthink $wrap "$@"
  765. }
  766.  
  767. # unicornthink
  768. #
  769. # Cows are boring
  770. #
  771. # NB: unicorn.cow obtained from https://github.com/schacon/cowsay/pull/13
  772. # Special Thanks to: Sven Wittevrongel (@CupOfTea696)
  773. #
  774. unicornthink()
  775. {
  776.     local wrap=-n
  777.     [ $# -gt 0 ] && wrap="-W $(( ${COLUMNS:-80} - 3 ))"
  778.     command cowthink -f ~/bin/unicorn.cow $wrap "$@"
  779. }
  780. fi # have cowthink
  781.  
  782. # path_munge [-pr] $entry ...
  783. #
  784. # Add $entry to $PATH if not already added, or (if given -r) remove $entry if
  785. # present. If given -p, prefix instead of append when adding $entry.
  786. #
  787. quietly unalias path_munge
  788. path_munge()
  789. {
  790.     local OPTIND=1 OPTARG flag
  791.     local newpath path
  792.     local oldIFS="$IFS" IFS
  793.     local prefix=
  794.     local remove=
  795.  
  796.     while getopts pr flag; do
  797.         case "$flag" in
  798.         p) prefix=1 ;;
  799.         r) remove=1 ;;
  800.         esac
  801.     done
  802.     shift $(( $OPTIND - 1 ))
  803.  
  804.     if [ "$remove" ]; then
  805.         while [ $# -gt 0 ]; do
  806.             newpath=
  807.             IFS=:
  808.             for path in $PATH; do
  809.                 [ "$path" = "$1" ] && continue
  810.                 newpath="$newpath${newpath:+:}$path"
  811.             done
  812.             IFS="$oldIFS"
  813.             PATH="$newpath"
  814.             shift
  815.         done
  816.     else
  817.         while [ $# -gt 0 ]; do
  818.             [ ! "$1" ] && shift && continue
  819.             ( PATH="$PATH:"
  820.               while [ "$PATH" ]; do
  821.                 [ "${PATH%%:*}" = "$1" ] && exit ${SUCCESS:-0}
  822.                 PATH="${PATH#*:}"
  823.               done
  824.               exit ${FAILURE:-1}
  825.             ) || {
  826.                 if [ "$prefix" ]; then
  827.                     export PATH="$1${PATH:+:}$PATH"
  828.                 else
  829.                     export PATH="$PATH${PATH:+:}$1"
  830.                 fi
  831.             }
  832.             shift
  833.         done
  834.     fi
  835. }
  836.  
  837. # fprintf $fd $fmt [ $opts ... ]
  838. #
  839. # Like printf, except allows you to print to a specific file-descriptor. Useful
  840. # for printing to stderr (fd=2) or some other known file-descriptor.
  841. #
  842. quietly unalias fprintf
  843. fprintf()
  844. {
  845.     local fd=$1
  846.     [ $# -gt 1 ] || return ${FAILURE:-1}
  847.     shift 1
  848.     printf "$@" >&$fd
  849. }
  850.  
  851. quietly unalias eprintf
  852. eprintf() { fprintf 2 "$@"; }
  853.  
  854. # pidof [-s] $process_name ...
  855. #
  856. # Print the pid(s) of each process matching the given name(s). If the `-s'
  857. # option is passed, only the first matching pid is returned.
  858. #
  859. # NB: Requires ps(1) awk(1) -- from base system
  860. #
  861. quietly unalias pidof
  862. pidof()
  863. {
  864.     local pids=
  865.     local single=0
  866.  
  867.     local OPTIND flag
  868.     while getopts s flag "$@"; do
  869.         case "$flag" in
  870.         s) single=1;;
  871.         esac
  872.     done
  873.     shift $(( $OPTIND - 1 ))
  874.  
  875.     local process_name process_pids=
  876.     while [ $# -gt 0 ]; do
  877.         process_name="$1"
  878.         process_pids=$(
  879.             ps axo pid=,ucomm= |
  880.             awk -v pattern="$process_name" \
  881.                 -v single=$single \
  882.             '
  883.                 BEGIN { space = "" }
  884.                 ( $2 ~ pattern ) \
  885.                 {
  886.                     printf "%c%s", space, $1
  887.                     if ( single ) exit
  888.                     space = " "
  889.                 }
  890.             '
  891.         )
  892.         pids="$pids${pids:+ }$process_pids"
  893.         shift
  894.     done
  895.  
  896.     [ "$pids" ] && echo "$pids"
  897. }
  898.  
  899. # settitle $title ...
  900. #
  901. # Set the title of your ANSI-compatible shell window.
  902. #
  903. quietly unalias settitle
  904. settitle()
  905. {
  906.     printf "\e]2;$*\a\e]1;$*\a\e]0;$*\a";
  907. }
  908.  
  909. # ssh-agent [ssh-agent options]
  910. #
  911. # Override ``ssh-agent'' to call a function (you can always call the real
  912. # binary by executing /usr/bin/ssh-agent) that launches a background ssh-agent
  913. # that times-out in 30 minutes.
  914. #
  915. # Will evaluate the output of /usr/bin/ssh-agent (the real ssh-agent) called
  916. # with either a known-secure set of arguments (if none are provided) or the
  917. # unmodified arguments to this functin.
  918. #
  919. # Purpose is to prevent memorizing something like ``eval "$( ssh-agent ... )"''
  920. # but instead simply ``ssh-agent [...]''.
  921. #
  922. # This allows you to, for example:
  923. #
  924. #   ssh-agent
  925. #   : do some ssh-add
  926. #   : do some commits
  927. #   ssh-agent -k
  928. #   : or instead of ``ssh-agent -k'' just wait 30m for it to die
  929. #
  930. # NB: Requires /usr/bin/ssh-agent -- from base system
  931. #
  932. quietly unalias ssh-agent
  933. ssh-agent()
  934. {
  935.     [ $# -gt 0 ] || set -- -t 1800
  936.     eval "$( /usr/bin/ssh-agent "$@" )"
  937. }
  938.  
  939. # ssh-agent-dup [-adnq]
  940. #
  941. # Connect to an open/active ssh-agent session available to the currently
  942. # authenticated user. If more than one ssh-agent is available and the `-n' flag
  943. # is not given, provide a menu list of open/active sessions available. Allows
  944. # the user to quickly duplicate access to an ssh-agent launched in another
  945. # interactive session on the same machine or for switching between agents.
  946. #
  947. # This allows you to, for example:
  948. #
  949. #   (in shell session A)
  950. #   ssh-agent
  951. #   (in shell session B)
  952. #   ssh-agent-dup
  953. #   (now both sessions A and B can use the same agent)
  954. #
  955. # No menu is presented if only a single agent session is available (the open
  956. # session is duplicated for the active shell session). If more than one agent
  957. # is available, a menu is presented. The menu choice becomes the active agent.
  958. #
  959. # If `-a' is present, list all readable agent sockets, not just those owned by
  960. # the currently logged-in user.
  961. #
  962. # If `-d' is present, disable the use of dialog, even if present.
  963. #
  964. # If `-n' is present, run non-interactively (good for scripts; pedantic).
  965. #
  966. # If `-q' is present, do not list agent nor keys.
  967. #
  968. # NB: Requires dialog_menutag() dialog_menutag2help() eval2() have()
  969. #     -- from this file
  970. # NB: Requires $DIALOG_TMPDIR $DIALOG_MENU_TAGS -- from this file
  971. # NB: Requires awk(1) cat(1) grep(1) id(1) ls(1) ps(1) ssh-add(1) stat(1)
  972. #     -- from base system
  973. #
  974. quietly unalias ssh-agent-dup
  975. ssh-agent-dup()
  976. {
  977.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  978.     local t=1s # ssh-add(1) timeout
  979.     local list_all= nodialog= quiet= interactive=1 noninteractive=
  980.     local sockn=1 sockets= sockstatout=
  981.     local owner socket socket_owner pid current_user
  982.     local listening ucomm sock
  983.     local dialog=dialog
  984.  
  985.     ! have "$dialog" && have bsddialog && dialog=bsddialog
  986.  
  987.     local OPTIND=1 OPTARG flag
  988.     while getopts adnq flag; do
  989.         case "$flag" in
  990.         a) list_all=1 ;;
  991.         d) nodialog=1 ;;
  992.         n) noninteractive=1 interactive= ;;
  993.         q) quiet=1 ;;
  994.         \?|*)
  995.             [ "$noninteractive" ] ||
  996.                 echo "$FUNCNAME [-adnq]" | ${LOLCAT:-cat} >&2
  997.             return ${FAILURE:-1}
  998.         esac
  999.     done
  1000.     shift $(( $OPTIND - 1 ))
  1001.  
  1002.     case "$UNAME_s" in
  1003.     *BSD) owner="-f%Su" ;;
  1004.     *) owner="-c%U"
  1005.     esac
  1006.  
  1007.     have sockstat && sockstatout=$( sockstat -wul )
  1008.  
  1009.     current_user=$( id -nu )
  1010.     for socket in /tmp/ssh-*/agent.[0-9]* $HOME/.ssh/agent/s.*.agent.*; do
  1011.         # Must exist as a socket
  1012.         [ -S "$socket" ] || continue
  1013.  
  1014.         if [ "$sockstatout" ]; then
  1015.             pid=$( echo "$sockstatout" | awk -v socket="$socket" '
  1016.                 $6==socket && ($2=="sshd" || $2=="ssh-agent") {
  1017.                     print $3; exit found++
  1018.                 } END { exit !found }
  1019.             ' ) || continue
  1020.             eval local _socket_pid$sockn=\$pid
  1021.         else
  1022.             # Must end in numbers-only (after trailing dot)
  1023.             pid="${socket##*.}"
  1024.             [ "$pid" -a "$pid" = "${pid#*[!0-9]}" ] || continue
  1025.             pid=$(( $pid + 1 )) # socket num is one below agent PID
  1026.  
  1027.             # Must be a running pid and an ssh or ssh-agent
  1028.             ucomm=$( ps -p $pid -o ucomm= 2> /dev/null )
  1029.             if ! [ "$ucomm" = ssh-agent ]; then
  1030.                 # This could be a forwarded agent
  1031.                 pid=$(( $pid - 1 ))
  1032.                 ucomm=$( ps -p $pid -o ucomm= 2> /dev/null )
  1033.                 [ "$ucomm" = sshd ] || continue
  1034.             fi
  1035.  
  1036.             # Must be owned by the current user unless `-a' is used
  1037.             # NB: When `-a' is used, socket still must be readable
  1038.             if [ ! "$list_all" ]; then
  1039.                 socket_owner=$( stat $owner "$socket" \
  1040.                     2> /dev/null ) || continue
  1041.                 [ "$socket_owner" = "$current_user" ] ||
  1042.                     continue
  1043.             fi
  1044.  
  1045.             eval local _socket_pid$sockn=\$pid
  1046.         fi
  1047.  
  1048.         sockets="$sockets $socket"
  1049.         sockn=$(( $sockn + 1 ))
  1050.     done
  1051.  
  1052.     sockets="${sockets# }"
  1053.     if [ ! "$sockets" ]; then
  1054.         if [ ! "$noninteractive" ]; then
  1055.             local msg="$FUNCNAME: No agent sockets available"
  1056.             echo "$msg" | ${LOLCAT:-cat} >&2
  1057.         fi
  1058.         return ${FAILURE:-1}
  1059.     fi
  1060.     if [ "$sockets" = "${sockets%% *}" ]; then
  1061.         # Only one socket found
  1062.         pid=$_socket_pid1
  1063.         ucomm=$( ps -p $pid -o ucomm= 2> /dev/null )
  1064.         if [ "$ucomm" = ssh-agent ] || [ "$ucomm" = sshd ]; then
  1065.             # local or forwarded agent
  1066.             eval${interactive:+2} export \
  1067.                 SSH_AUTH_SOCK="$sockets" \
  1068.                 SSH_AGENT_PID="$pid"
  1069.         else
  1070.             eval${interactive:+2} export \
  1071.                 SSH_AUTH_SOCK="$sockets"
  1072.         fi
  1073.         [ "$SSH_AGENT_PID" -a ! "$quiet" ] && # show process
  1074.             [ "$interactive" ] &&
  1075.             ps -p "$SSH_AGENT_PID" | ${LOLCAT:-cat}
  1076.         # dump fingerprints from newly configured agent
  1077.         if ! [ "$quiet" -o "$noninteractive" ]; then
  1078.             echo "# NB: Use \`ssh-agent -k' to kill this agent"
  1079.             timeout $t ssh-add -l
  1080.         fi | ${LOLCAT:-cat}
  1081.         return ${SUCCESS:-0}
  1082.     fi
  1083.  
  1084.     # There's more than one agent available
  1085.     [ "$noninteractive" ] && return ${FAILURE:-1}
  1086.  
  1087.     #
  1088.     # If we don't have dialog(1) or bsddialog(1), print possible values
  1089.     #
  1090.     if [ "$nodialog" ] || ! have "$dialog"; then
  1091.         local prefix="%3s"
  1092.         local fmt="$prefix %5s %-20s %s\n"
  1093.         local num=0 choice
  1094.         local identities nloaded
  1095.  
  1096.         sockets=$( command ls -tr $sockets ) # ascending order by age
  1097.         printf "$fmt" "" PID USER+NKEYS COMMAND
  1098.         sockn=1
  1099.         for socket in $sockets; do
  1100.             num=$(( $num + 1 ))
  1101.             eval pid=\$_socket_pid$sockn
  1102.             ucomm=$( ps -p $pid -o ucomm= 2> /dev/null )
  1103.             nkeys=0
  1104.             identities=$( SSH_AUTH_SOCK="$socket" \
  1105.                 timeout $t ssh-add -l
  1106.             ) && nkeys=$( echo "$identities" | grep -c . )
  1107.             printf "$fmt" $num: "$pid" \
  1108.                 "$( ps -p $pid -o user= )"+"$nkeys" \
  1109.                 "$( ps -p $pid -o command= )" | ${LOLCAT:-cat}
  1110.             sockn=$(( $sockn + 1 ))
  1111.         done
  1112.         echo
  1113.         echo -n "Select a number [$num]: " | ${LOLCAT:-cat}
  1114.         read choice
  1115.         : ${choice:=$num}
  1116.         case "$choice" in
  1117.         ""|*[!0-9]*)
  1118.             echo "$FUNCNAME: Invalid choice [$choice]" |
  1119.                 ${LOLCAT:-cat} >&2
  1120.             return ${FAILURE:-1} ;;
  1121.         esac
  1122.         if [ $choice -gt $num -o $choice -lt 1 ]; then
  1123.             echo "$FUNCNAME: Choice out of range [$choice]" |
  1124.                 ${LOLCAT:-cat} >&2
  1125.             return ${FAILURE:-1}
  1126.         fi
  1127.         set -- $sockets
  1128.         eval socket=\"\${$choice}\"
  1129.  
  1130.         sockn=0
  1131.         for sock in $sockets; do
  1132.             sockn=$(( $sockn + 1 ))
  1133.             [ "$sock" = "$socket" ] || continue
  1134.             break
  1135.         done
  1136.         eval pid=\$_socket_pid$sockn
  1137.         ucomm=$( ps -p $pid -o ucomm= 2> /dev/null )
  1138.         if [ "$ucomm" = ssh-agent ] || [ "$ucomm" = sshd ]; then
  1139.             # local or forwarded agent
  1140.             eval2 export \
  1141.                 SSH_AUTH_SOCK="$socket" \
  1142.                 SSH_AGENT_PID="$pid"
  1143.         else
  1144.             eval2 export SSH_AUTH_SOCK="$socket"
  1145.         fi
  1146.     else
  1147.         local menu_list=
  1148.  
  1149.         sockets=$( command ls -1t $sockets ) # descending order by age
  1150.         sockn=0
  1151.         for sock in $sockets; do
  1152.             sockn=$(( $sockn + 1 ))
  1153.             export _socket_pid$sockn
  1154.         done
  1155.         menu_list=$( echo "$sockets" |
  1156.             awk -v t="$t" -v tags="$DIALOG_MENU_TAGS" '
  1157.             BEGIN { sockn = 1 }
  1158.             {
  1159.                 if (++tagn > length(tags)) exit
  1160.                 pid = ENVIRON["_socket_pid" sockn++]
  1161.                 cmd = sprintf("ps -p %u -o user=", pid)
  1162.                 cmd | getline user
  1163.                 close(cmd)
  1164.                 cmd = sprintf("ps -p %u -o command=", pid)
  1165.                 cmd | getline command
  1166.                 close(cmd)
  1167.                 nloaded = 0
  1168.                 cmd = "SSH_AUTH_SOCK=" $0 \
  1169.                     " timeout " t " ssh-add -l"
  1170.                 while (cmd | getline identity) {
  1171.                     nloaded += identity ~ /^[[:digit:]]/
  1172.                 }
  1173.                 close(cmd)
  1174.                 printf "'\'%s\'\ \'%s\'\ \'%s\''\n",
  1175.                     substr(tags, tagn, 1),
  1176.                     sprintf("pid %u %s+%u %s",
  1177.                         pid, user, nloaded, command),
  1178.                     sprintf("export %s %s",
  1179.                         "SSH_AUTH_SOCK=" $0,
  1180.                         "SSH_AGENT_PID=" pid)
  1181.             }'
  1182.         )
  1183.  
  1184.         local prompt="Pick an ssh-agent to duplicate (user+nkeys):"
  1185.         eval $dialog \
  1186.             --clear --title "'$FUNCNAME'" --item-help \
  1187.             --menu "'$prompt'" 17 55 9 $menu_list \
  1188.             2> "$DIALOG_TMPDIR/dialog.menu.$$"
  1189.         local retval=$?
  1190.  
  1191.         # Return if "Cancel" was chosen (-1) or ESC was pressed (255)
  1192.         [ $retval -eq ${SUCCESS:-0} ] || return $retval
  1193.  
  1194.         local tag="$( dialog_menutag )"
  1195.         eval2 $( eval dialog_menutag2help "'$tag'" $menu_list )
  1196.     fi
  1197.  
  1198.     # Attempt to show the running agent
  1199.     [ "$SSH_AGENT_PID" -a ! "$quiet" ] &&
  1200.         ps -p "$SSH_AGENT_PID" | ${LOLCAT:-cat}
  1201.  
  1202.     # Attempt to dump fingerprints from newly configured agent
  1203.     if [ ! "$quiet" ]; then
  1204.         echo "# NB: Use \`$FUNCNAME' to select a different agent"
  1205.         echo "# NB: Use \`ssh-agent -k' to kill this agent"
  1206.         timeout $t ssh-add -l
  1207.     fi | ${LOLCAT:-cat}
  1208. }
  1209.  
  1210. # openkey [-hv]
  1211. #
  1212. # Mounts my F.o thumb
  1213. #
  1214. # NB: Requires eprintf() have() -- from this file
  1215. # NB: Requires awk(1) df(1) id(1) mount(8) -- from base system
  1216. #
  1217. quietly unalias openkey
  1218. openkey()
  1219. {
  1220.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  1221.     [ "$UNAME_s" = "FreeBSD" ] ||
  1222.         { echo "$FUNCNAME: FreeBSD only!" >&2; return 1; }
  1223.     local OPTIND=1 OPTARG flag verbose= sudo=
  1224.     while getopts hv flag; do
  1225.         case "$flag" in
  1226.         v) verbose=1 ;;
  1227.         *) local optfmt="\t%-4s %s\n"
  1228.            eprintf "Usage: $FUNCNAME [-hv]\n"
  1229.            eprintf "OPTIONS:\n"
  1230.            eprintf "$optfmt" "-h" \
  1231.                    "Print this text to stderr and return."
  1232.            eprintf "$optfmt" "-v" \
  1233.                    "Print verbose debugging information."
  1234.            return ${FAILURE:-1}
  1235.         esac
  1236.     done
  1237.     shift $(( $OPTIND - 1 ))
  1238.     if [ "$( id -u )" != "0" ]; then
  1239.         if have sr; then
  1240.             sudo=sr
  1241.         elif have sudo; then
  1242.             sudo=sudo
  1243.         fi || {
  1244.             eprintf "$FUNCNAME: not enough privileges\n"
  1245.             return ${FAILURE:-1}
  1246.         }
  1247.     fi
  1248.     df -l /mnt | awk '
  1249.         $NF == "/mnt" { exit found++ } END { exit !found }
  1250.     ' || ${verbose:+eval2} $sudo mount /mnt || return
  1251.     local nfail=3
  1252.     while [ $nfail -gt 0 ]; do
  1253.         /mnt/mount.sh -d${verbose:+v} && break
  1254.         nfail=$(( $nfail - 1 ))
  1255.     done
  1256.     [ "$verbose" ] && df -hT /mnt/* | ( awk '
  1257.         NR == 1 { print > "/dev/stderr"; next } 1
  1258.     ' | sort -u ) 2>&1
  1259.     return ${SUCCESS:-0}
  1260. }
  1261.  
  1262. # closekey [-ehv]
  1263. #
  1264. # Unmounts my F.o thumb
  1265. #
  1266. # NB: Requires eprintf() have() -- from this file
  1267. # NB: Requires awk(1) camcontrol(8) df(1) id(1) umount(8) -- from base system
  1268. #
  1269. quietly unalias closekey
  1270. closekey()
  1271. {
  1272.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  1273.     local OPTIND=1 OPTARG flag eject= verbose= sudo=
  1274.     while getopts ehv flag; do
  1275.         case "$flag" in
  1276.         e) eject=1 ;;
  1277.         v) verbose=1 ;;
  1278.         *) local optfmt="\t%-4s %s\n"
  1279.            eprintf "Usage: $FUNCNAME [-ehv]\n"
  1280.            eprintf "OPTIONS:\n"
  1281.            eprintf "$optfmt" "-e" \
  1282.                    "Eject USB media (using \`camcontrol eject')."
  1283.            eprintf "$optfmt" "-h" \
  1284.                    "Print this text to stderr and return."
  1285.            eprintf "$optfmt" "-v" \
  1286.                    "Print verbose debugging information."
  1287.            return ${FAILURE:-1}
  1288.         esac
  1289.     done
  1290.     shift $(( $OPTIND - 1 ))
  1291.     if [ "$( id -u )" != "0" ]; then
  1292.         if have sr; then
  1293.             sudo=sr
  1294.         elif have sudo; then
  1295.             sudo=sudo
  1296.         fi || {
  1297.             eprintf "$FUNCNAME: not enough privileges\n"
  1298.             return ${FAILURE:-1}
  1299.         }
  1300.     fi
  1301.     [ ! -f "/mnt/umount.sh" ] ||
  1302.         ${verbose:+eval2} /mnt/umount.sh ${verbose:+-v} || return
  1303.     [ ! "$eject" ] || daN=$( df -l /mnt | awk '
  1304.         $NF == "/mnt" && match($0, "^/dev/[[:alpha:]]+[[:digit:]]+") {
  1305.             print substr($0, 6, RLENGTH - 5)
  1306.             exit found++
  1307.         } END { exit ! found }
  1308.     ' ) || daN=$(
  1309.         [ "$sudo" -a "$verbose" ] && echo $sudo camcontrol devlist >&2
  1310.         $sudo camcontrol devlist | awk '
  1311.         BEGIN {
  1312.             camfmt = "^<%s>[[:space:]]+[^(]*"
  1313.  
  1314.             disk[nfind = 0] = "da[[:digit:]]+"
  1315.             find[nfind++] = "USB Flash Disk 1100"
  1316.  
  1317.             disk[nfind] = "da[[:digit:]]+"
  1318.             find[nfind++] = "PNY USB 2.0 FD PMAP"
  1319.  
  1320.             #disk[nfind] = "device_pattern"
  1321.             #find[nfind++] = "model_pattern"
  1322.         }
  1323.         found = 0
  1324.         {
  1325.             for (n = 0; n < nfind; n++)
  1326.             {
  1327.                 if (!match($0, sprintf(camfmt, find[n])))
  1328.                     continue
  1329.                 devicestr = substr($0, RSTART + RLENGTH + 1)
  1330.                 gsub(/\).*/, "", devicestr)
  1331.                 ndevs = split(devicestr, devices, /,/)
  1332.                 for (d = 1; d <= ndevs; d++) {
  1333.                     if (devices[d] !~ "^" disk[n] "$")
  1334.                         continue
  1335.                     found = 1
  1336.                     break
  1337.                 }
  1338.                 if (found) break
  1339.             }
  1340.         }
  1341.         found && $0 = devices[d] { print; exit }
  1342.         END { exit !found }
  1343.     ' ) || return
  1344.     ! df -l /mnt | awk '$NF=="/mnt"{exit found++}END{exit !found}' ||
  1345.         ${verbose:+eval2} $sudo umount /mnt || return
  1346.     [ "$eject" -a "$daN" ] &&
  1347.         ${verbose:+eval2} $sudo camcontrol eject "$daN"
  1348.     return ${SUCCESS:-0}
  1349. }
  1350.  
  1351. # loadkeys [OPTIONS] [key ...]
  1352. #
  1353. # Load my SSH private keys from my F.o thumb. The `key' argument is to the
  1354. # SSH private keyfile's suffix; in example, "sf" for "id_rsa.sf" or "f.o" for
  1355. # "id_rsa.f.o" or "gh" for "id_rsa.gh".
  1356. #
  1357. # For example, to load the Sourceforge.net key, F.o key, and Github key:
  1358. #   loadkeys sf f.o gh
  1359. #
  1360. # OPTIONS:
  1361. #   -c           Close USB media after loading keys.
  1362. #   -e           Close and eject USB media after loading keys.
  1363. #   -h           Print this text to stderr and return.
  1364. #   -k           Kill running ssh-agent(1) and launch new one.
  1365. #   -n           Start a new ssh-agent, ignoring current one.
  1366. #   -t timeout   Timeout. Only used if starting ssh-agent(1).
  1367. #   -v           Print verbose debugging information.
  1368. #
  1369. # NB: Requires closekey() colorize() eprintf() openkey() quietly() ssh-agent()
  1370. #     ssh-agent-dup() -- from this file
  1371. # NB: Requires awk(1) kill(1) ps(1) ssh-add(1) -- from base system
  1372. #
  1373. quietly unalias loadkeys
  1374. loadkeys()
  1375. {
  1376.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  1377.     local OPTIND=1 OPTARG flag close= eject= kill= new= timeout= verbose=
  1378.     while getopts cehknt:v flag; do
  1379.         case "$flag" in
  1380.         c) close=1 ;;
  1381.         e) close=1 eject=1 ;;
  1382.         k) kill=1 ;;
  1383.         n) new=1 ;;
  1384.         v) verbose=1 ;;
  1385.         t) timeout="$OPTARG" ;;
  1386.         *) local optfmt="\t%-12s %s\n"
  1387.            eprintf "Usage: $FUNCNAME [OPTIONS] [key ...]\n"
  1388.            eprintf "OPTIONS:\n"
  1389.            eprintf "$optfmt" "-c" \
  1390.                    "Close USB media after loading keys."
  1391.            eprintf "$optfmt" "-e" \
  1392.                    "Close and eject USB media after loading keys."
  1393.            eprintf "$optfmt" "-h" \
  1394.                    "Print this text to stderr and return."
  1395.            eprintf "$optfmt" "-k" \
  1396.                    "Kill running ssh-agent(1) and launch new one."
  1397.            eprintf "$optfmt" "-n" \
  1398.                    "Start a new ssh-agent, ignoring current one."
  1399.            eprintf "$optfmt" "-t timeout" \
  1400.                    "Timeout. Only used if starting ssh-agent(1)."
  1401.            eprintf "$optfmt" "-v" \
  1402.                    "Print verbose debugging information."
  1403.            return ${FAILURE:-1}
  1404.         esac
  1405.     done
  1406.     shift $(( $OPTIND - 1 ))
  1407.     [ "$kill" ] && quietly ssh-agent -k
  1408.     if [ "$new" ]; then
  1409.         ssh-agent ${timeout:+-t"$timeout"} ||
  1410.             return ${FAILURE:-1}
  1411.     elif quietly kill -0 "$SSH_AGENT_PID"; then
  1412.         : already running
  1413.     elif [ "$SSH_AUTH_SOCK" ] && quietly ssh-add -l; then
  1414.         eval2 export SSH_AGENT_PID=$( lsof -t -- $SSH_AUTH_SOCK )
  1415.     else
  1416.         if ! ssh-agent-dup -q; then
  1417.             ssh-agent ${timeout:+-t"$timeout"} ||
  1418.                 return ${FAILURE:-1}
  1419.         fi
  1420.     fi
  1421.     ps -p "$SSH_AGENT_PID" || return ${FAILURE:-1}
  1422.     local suffix file show= load_required=
  1423.     [ $# -eq 0 ] && load_required=1
  1424.     for suffix in "$@"; do
  1425.         file="/mnt/keys/id_rsa.$suffix"
  1426.         ssh-add -l | awk -v file="$file" '
  1427.             gsub(/(^[0-9]+ [[:xdigit:]:]+ | \(.*\).*$)/, "") &&
  1428.                 $0 == file { exit found++ }
  1429.             END { exit !found }
  1430.         ' && show="$show${show:+|}$suffix" && continue # already loaded
  1431.         load_required=1
  1432.         break
  1433.     done
  1434.     ssh-add -l | colorize -c 36 "/mnt/keys/id_rsa\\.($show)([[:space:]]|$)"
  1435.     [ "$load_required" ] || return ${SUCCESS:-0}
  1436.     openkey ${verbose:+-v} || return ${FAILURE:-1}
  1437.     [ "$verbose" ] && ssh-add -l
  1438.     local loaded_new=
  1439.     if [ $# -gt 0 ]; then
  1440.         for suffix in "$@"; do
  1441.             file="/mnt/keys/id_rsa.$suffix"
  1442.             [ -f "$file" ] || continue
  1443.             ssh-add -l | awk -v file="$file" '
  1444.                 gsub(/(^[0-9]+ [[:xdigit:]:]+ | \(.*\).*$)/,
  1445.                     "") && $0 == file { exit found++ }
  1446.                 END { exit !found }
  1447.             ' && continue
  1448.             ssh-add "$file" || continue
  1449.             loaded_new=1
  1450.             show="$show${show:+|}$suffix"
  1451.         done
  1452.     else
  1453.         for file in /mnt/keys/id_rsa.*; do
  1454.             [ -e "$file" ] || continue
  1455.             [ "$file" != "${file%.[Pp][Uu][Bb]}" ] && continue
  1456.             ssh-add -l | awk -v file="$file" '
  1457.                 gsub(/(^[0-9]+ [[:xdigit:]:]+ | \(.*\).*$)/,
  1458.                     "") && $0 == file { exit found++ }
  1459.                 END { exit !found }
  1460.             ' && continue
  1461.             ssh-add "$file" || continue
  1462.             loaded_new=1
  1463.             show="$show${show:+|}${file#/mnt/keys/id_rsa.}"
  1464.         done
  1465.     fi
  1466.     [ "$close" ] && closekey ${verbose:+-v} ${eject:+-e}
  1467.     [ "$loaded_new" ] && ssh-add -l |
  1468.         colorize -c 36 "/mnt/keys/id_rsa\\.($show)([[:space:]]|$)"
  1469. }
  1470.  
  1471. # unloadkeys [OPTIONS] [key ...]
  1472. #
  1473. # Unload my SSH private keys from my F.o thumb. The `key' argument is to the
  1474. # SSH private keyfile's suffix; in example, "sf" for "id_rsa.sf" or "f.o" for
  1475. # "id_rsa.f.o" or "gh" for "id_rsa.gh".
  1476. #
  1477. # For example, to unload the Sourceforge.net key, F.o key, and Github key:
  1478. #   unloadkeys sf f.o gh
  1479. #
  1480. # OPTIONS:
  1481. #   -a           Unload all keys.
  1482. #   -c           Close USB media after unloading keys.
  1483. #   -e           Close and eject USB media after unloading keys.
  1484. #   -h           Print this text to stderr and return.
  1485. #   -v           Print verbose debugging information.
  1486. #
  1487. # NB: Requires closekey() colorize() eprintf() openkey() quietly()
  1488. #     -- from this file
  1489. # NB: Requires awk(1) ps(1) ssh-add(1) -- from base system
  1490. #
  1491. quietly unalias unloadkeys
  1492. unloadkeys()
  1493. {
  1494.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  1495.     local OPTIND=1 OPTARG flag all= close= eject= verbose=
  1496.     while getopts acehv flag; do
  1497.         case "$flag" in
  1498.         a) all=1 ;;
  1499.         c) close=1 ;;
  1500.         e) close=1 eject=1 ;;
  1501.         v) verbose=1 ;;
  1502.         *) local optfmt="\t%-12s %s\n"
  1503.            eprintf "Usage: $FUNCNAME [OPTIONS] [key ...]\n"
  1504.            eprintf "OPTIONS:\n"
  1505.            eprintf "$optfmt" "-a" "Unload all keys."
  1506.            eprintf "$optfmt" "-c" \
  1507.                    "Close USB media after loading keys."
  1508.            eprintf "$optfmt" "-e" \
  1509.                    "Close and eject USB media after loading keys."
  1510.            eprintf "$optfmt" "-h" \
  1511.                    "Print this text to stderr and return."
  1512.            eprintf "$optfmt" "-v" \
  1513.                    "Print verbose debugging information."
  1514.            return ${FAILURE:-1}
  1515.         esac
  1516.     done
  1517.     shift $(( $OPTIND - 1 ))
  1518.     local suffix file show= unload_required=
  1519.     if [ "$all" ]; then
  1520.         unload_required=1
  1521.         shift $#
  1522.     fi
  1523.     for suffix in "$@"; do
  1524.         file="/mnt/keys/id_rsa.$suffix"
  1525.         ssh-add -l | awk -v file="$file" '
  1526.             gsub(/(^[0-9]+ [[:xdigit:]:]+ | \(.*\).*$)/, "") &&
  1527.                 $0 == file { exit found++ }
  1528.             END { exit !found }
  1529.         ' || continue # not loaded
  1530.         show="$show${show:+|}$suffix"
  1531.         unload_required=1
  1532.         break
  1533.     done
  1534.     ssh-add -l | colorize -c 31 "/mnt/keys/id_rsa\\.($show)([[:space:]]|$)"
  1535.     [ "$unload_required" ] || return ${SUCCESS:-0}
  1536.     openkey ${verbose:+-v} || return ${FAILURE:-1}
  1537.     [ "$verbose" ] && ssh-add -l
  1538.     if [ "$all" ]; then
  1539.         ssh-add -D
  1540.     else
  1541.         for suffix in "$@"; do
  1542.             file="/mnt/keys/id_rsa.$suffix"
  1543.             [ -f "$file" ] || continue
  1544.             ssh-add -l | awk -v file="$file" '
  1545.                 gsub(/(^[0-9]+ [[:xdigit:]:]+ | \(.*\).*$)/,
  1546.                     "") && $0 == file { exit found++ }
  1547.                 END { exit !found }
  1548.             ' || continue
  1549.             ssh-add -d "$file"
  1550.         done
  1551.     fi
  1552.     [ "$close" ] && closekey ${verbose:+-v} ${eject:+-e}
  1553.     [ "$all" ] || ssh-add -l |
  1554.         colorize -c 36 "/mnt/keys/id_rsa\\.($show)([[:space:]]|$)"
  1555. }
  1556.  
  1557. # zless [OPTIONS] $file ...
  1558. #
  1559. # Allow quick paging of gzip-compressed files. Any options passed in-addition
  1560. # to the filename pertain to zcat(1).
  1561. #
  1562. # NOTE: Some systems provide zless as an actual utility. For those systems,
  1563. # we'll fallback to the actual utility opposed to this function.
  1564. #
  1565. if ! have zless; then
  1566.     zless()
  1567.     {
  1568.         zcat "$@" | less
  1569.     }
  1570. fi
  1571.  
  1572. # zlog $logfile [$pattern]
  1573. #
  1574. # A general purpose log searching function. Given $log base pathname, this
  1575. # function will search for all occurrences of $pattern in $logfile and
  1576. # $logfile.N.gz [FreeBSD] or $logfile.N [Linux] (preserving reverse-chrono-
  1577. # logical order, searching oldest logfiles first).
  1578. #
  1579. # If $pattern is NULL or omitted, all lines are returned.
  1580. #
  1581. # NOTE: $pattern is an awk regular expression.
  1582. #
  1583. quietly unalias zlog
  1584. zlog()
  1585. {
  1586.     local logfile="$1" pattern="$2"
  1587.     local logfiles="$logfile" gzlogfiles="" n=0
  1588.     local sudo= needsudo=
  1589.  
  1590.     #
  1591.     # Check for two conditions where we would need sudo
  1592.     # 1. If the log file is not readable
  1593.     # 2. If the parent directory is not readable/traversable
  1594.     #
  1595.     [ -r "$logfile" ] || needsudo=1
  1596.     case "$logfile" in
  1597.     */*) [ -r "${logfile%/*}" ] || needsudo=1;;
  1598.     esac
  1599.  
  1600.     if [ "$needsudo" ]; then
  1601.         if [ "$UNAME_s" = "Linux" -a "$Linux" = "Ubuntu" ]; then
  1602.             sudo=sudo
  1603.         else
  1604.             if have sr; then
  1605.                 sudo=sr
  1606.             elif have sudo; then
  1607.                 sudo=sudo
  1608.             fi
  1609.         fi
  1610.     fi
  1611.  
  1612.     case "$UNAME_s" in
  1613.     FreeBSD)
  1614.         #
  1615.         # FreeBSD rotates logs in the following fashion:
  1616.         #
  1617.         # FILENAME        DESCRIPTION
  1618.         # logfile         current log file
  1619.         # logfile.0.gz    most-recently rotated log file
  1620.         # logfile.1.gz    second-most recently rotated log file
  1621.         #
  1622.         local n=0
  1623.         if [ "$needsudo" ]; then
  1624.             while $sudo [ -f "$logfile.$n.gz" ]; do
  1625.                 gzlogfiles="$logfile.$n.gz $gzlogfiles"
  1626.                 n=$(( $n + 1 ))
  1627.             done
  1628.             if [ ! "$gzlogfiles" ]; then
  1629.                 n=0
  1630.                 while $sudo [ -f "$logfile.$n.bz2" ]; do
  1631.                     gzlogfiles="$logfile.$n.bz2 $gzlogfiles"
  1632.                     n=$(( $n + 1 ))
  1633.                 done
  1634.             fi
  1635.         else
  1636.             while [ -f "$logfile.$n.gz" ]; do
  1637.                 [ -r "$logfile.$n.gz" ] || needsudo=1
  1638.                 gzlogfiles="$logfile.$n.gz $gzlogfiles"
  1639.                 n=$(( $n + 1 ))
  1640.             done
  1641.             if [ ! "$gzlogfiles" ]; then
  1642.                 n=0
  1643.                 while $sudo [ -f "$logfile.$n.bz2" ]; do
  1644.                     gzlogfiles="$logfile.$n.bz2 $gzlogfiles"
  1645.                     n=$(( $n + 1 ))
  1646.                 done
  1647.             fi
  1648.         fi
  1649.         ;;
  1650.     Linux)
  1651.         #
  1652.         # Linux rotates logs in the following fashion:
  1653.         #
  1654.         # FILENAME     DESCRIPTION
  1655.         # logfile      current log file
  1656.         # logfile.1    most-recently rotated log file
  1657.         # logfile.2    second-most recently rotated log file
  1658.         #
  1659.         local n=1
  1660.         if [ "$needsudo" ]; then
  1661.             while $sudo [ -f "$logfile.$n" ]; do
  1662.                 logfiles="$logfile.$n $logfiles"
  1663.                 n=$(( $n + 1 ))
  1664.             done
  1665.         else
  1666.             while [ -f "$logfile.$n" ]; do
  1667.                 [ -r "$logfile.$n" ] || needsudo=1
  1668.                 logfiles="$logfile.$n $logfiles"
  1669.                 n=$(( $n + 1 ))
  1670.             done
  1671.         fi
  1672.         ;;
  1673.     esac
  1674.  
  1675.     if [ "$gzlogfiles" ]; then
  1676.         $sudo zcat $gzlogfiles \
  1677.             | sh -c "cat; cat $logfiles" \
  1678.             | awk "/$pattern/ {print}"
  1679.     else
  1680.         $sudo cat $logfiles \
  1681.             | awk "/$pattern/ {print}"
  1682.     fi
  1683. }
  1684.  
  1685. # zlog_summary $logfile [-d1,2,3] [$pattern]
  1686. #
  1687. # A wrapper around the zlog general purpose log searching function designed to
  1688. # provide a brief summary containing the following information:
  1689. #   - The first line matching $pattern
  1690. #   - The timestamp of the first occurrence
  1691. #   - The timestamp of the last occurrence
  1692. #   - How many occurrences were found
  1693. #     NOTE: Also counts "last message repeated N times" entries
  1694. #
  1695. # NOTE: If $pattern is NULL or omitted, the first/oldest log-entry is printed.
  1696. #       In addition, the timestamps in the summary will instead be the first
  1697. #       (oldest) and last (newest) entry, respectively. This serves as a sort
  1698. #       of brief look at the date-range spanning the individual log files.
  1699. #
  1700. # NOTE: $pattern is an awk regular expression.
  1701. #
  1702. # By default, it is assumed that the date/time fields to be displayed are the
  1703. # first, second, and third fields of each log entry, separated by whitespace.
  1704. # For example, /var/log/messages has the following first three fields:
  1705. #
  1706. #   Jun  5 04:02:10
  1707. #
  1708. # However, not all logfiles display date/time entries in the above manner.
  1709. # Therefore, the following options can be passed to customize which line-fields
  1710. # (and how many) are displayed for the date/time:
  1711. #
  1712. # For example, the Apache error_log displays the date/time in five pieces:
  1713. #
  1714. #   [Sun May 31 04:02:14 2009]
  1715. #
  1716. # So to display the proper values for date-range outputs when parsing the
  1717. # Apache error_log, you should pass the following parameters:
  1718. #
  1719. #   -d1,2,3,4,5
  1720. #
  1721. # You can optionally pass `-dNF' to print the whole line.
  1722. #
  1723. # NB: Requires zlog() -- from this file
  1724. # NB: Requires awk(1) -- from base system
  1725. #
  1726. quietly unalias zlog_summary
  1727. zlog_summary()
  1728. {
  1729.     local logfile="$1"
  1730.     local datetime="1,2,3"
  1731.  
  1732.     shift 1 # logfile
  1733.  
  1734.     local OPTIND flag
  1735.     while getopts d: flag; do
  1736.         case "$flag" in
  1737.         d) datetime="$OPTARG";;
  1738.         esac
  1739.     done
  1740.     shift $(( $OPTIND - 1 ))
  1741.  
  1742.     local pattern="$1"
  1743.     zlog "$logfile" |
  1744.         awk -v pattern="$pattern" -v datetime="$datetime" '
  1745.     BEGIN {
  1746.         hr = sprintf("%-60s", "")
  1747.         gsub(" ", "-", hr)
  1748.         count = init = crepeat = 0
  1749.         last = ""
  1750.         ndt = split(datetime, dt, /,/)
  1751.     }
  1752.     {
  1753.         if ($0 !~ pattern && !crepeat) next
  1754.         else if (crepeat)
  1755.         {
  1756.             if ($0 !~ /repeated/) {
  1757.                 crepeat = 0
  1758.                 next
  1759.             }
  1760.             count += $8
  1761.             if (length(datetime) <= 0) next
  1762.             last = ""
  1763.             for (n = 1; n <= ndt; n++) last = sprintf("%s%s%s",
  1764.                 last, (length(last) > 0 ? " " : ""), $dt[n])
  1765.             next
  1766.         }
  1767.         count++
  1768.         if (!init)
  1769.         {
  1770.             print hr
  1771.             print $0
  1772.             print hr
  1773.             printf(" 1st:")
  1774.             if (length(datetime) > 0)
  1775.                 for (n = 1; n <= ndt; n++)
  1776.                     printf(" %s", $dt[n])
  1777.             printf("\n")
  1778.             init = 1
  1779.         }
  1780.         crepeat = 1
  1781.         if (length(datetime) > 0) {
  1782.             last = ""
  1783.             for (n = 1; n <= ndt; n++) last = sprintf("%s%s%s",
  1784.                 last, (length(last) > 0 ? " " : ""), $dt[n])
  1785.         }
  1786.     }
  1787.     END {
  1788.         print "Last: " last
  1789.         print "Total Occurrences: " count
  1790.         print hr
  1791.     }
  1792.     ' # END-QUOTE
  1793. }
  1794.  
  1795. # zlog_usage [$FUNCNAME]
  1796. #
  1797. # Print usage statement for zlog_wrapper family of functions.
  1798. #
  1799. # NB: Requires eprintf() -- from this file
  1800. #
  1801. quietly unalias zlog_usage
  1802. zlog_usage()
  1803. {
  1804.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  1805.     local func="${1:-$FUNCNAME}"
  1806.     local optfmt='\t%-12s %s\n'
  1807.  
  1808.     eprintf "Usage: %s [OPTIONS] [PATTERN]\n" "$func"
  1809.     eprintf "Arguments:\n"
  1810.     eprintf "$optfmt" "PATTERN" \
  1811.             "Awk(1) regular expression pattern to search logfile for."
  1812.  
  1813.     eprintf "\n"
  1814.  
  1815.     eprintf "Options:\n"
  1816.     eprintf "$optfmt" "-h" \
  1817.             "Print this usage statement and exit."
  1818.     eprintf "$optfmt" "-v" \
  1819.             "Verbose. Show individual matching lines."
  1820.     eprintf "$optfmt" "-d1,2,3" \
  1821.             "Comma-separated list of field numbers to display as the"
  1822.     eprintf "$optfmt" "" \
  1823.             "date/time when providing summary output (ignored if \`-v'"
  1824.     eprintf "$optfmt" "" \
  1825.             "is passed). Default is 1,2,3. A value of \`NF' prints the"
  1826.     eprintf "$optfmt" "" \
  1827.             "entire line."
  1828.  
  1829.     eprintf "\n"
  1830.  
  1831.     return ${FAILURE:-1}
  1832. }
  1833.  
  1834. # zlog_wrapper $FUNCNAME $logfile [OPTIONS] [$pattern]
  1835. #
  1836. # A wrapper for the zlog/zlog_summary functions.
  1837. #
  1838. # NB: Requires zlog() zlog_summary() zlog_usage() -- from this file
  1839. #
  1840. quietly unalias zlog_wrapper
  1841. zlog_wrapper()
  1842. {
  1843.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  1844.     local func="${1:-$FUNCNAME}"
  1845.     local logfile="$2"
  1846.     local datetime=
  1847.     local verbose=
  1848.  
  1849.     shift 2 # func/logfile
  1850.  
  1851.     local OPTIND flag
  1852.     while getopts d:hv flag; do
  1853.         case "$flag" in
  1854.         d) datetime="$OPTARG";;
  1855.         v) verbose=1;;
  1856.         h|\?)
  1857.             zlog_usage "$func"
  1858.             return ${FAILURE:-1}
  1859.             ;;
  1860.         esac
  1861.     done
  1862.     shift $(( $OPTIND - 1 ))
  1863.  
  1864.     if [ "$verbose" ]; then
  1865.         zlog "$logfile" "$@"
  1866.     else
  1867.         zlog_summary "$logfile" ${datetime:+-d"$datetime"} "$@"
  1868.     fi
  1869. }
  1870.  
  1871. # tlog $log [OPTIONS]
  1872. #
  1873. # A general purpose wrapper to tail(1) that checks if the destination logfile
  1874. # is readable by you. If the file is readable by your effective UID, this
  1875. # command is equivalent to execute "tail -F [options] $log", otherwise one of
  1876. # sudo(8) or sr(8) is used to provide root-privileges to read the logfile.
  1877. #
  1878. # NB: Requires eval2() have() -- from this file
  1879. # NB: Requires tail(1) -- from base system
  1880. #
  1881. quietly unalias tlog
  1882. tlog()
  1883. {
  1884.     local logfile="$1"
  1885.     local sudo= needsudo=
  1886.     shift 1 # logfile
  1887.  
  1888.     #
  1889.     # Check for two conditions where we would need sudo
  1890.     # 1. If the log file is not readable
  1891.     # 2. If the parent directory is not readable/traversable
  1892.     #
  1893.     [ -r "$logfile" ] || needsudo=1
  1894.     case "$logfile" in
  1895.     */*) [ -r "${logfile%/*}" ] || needsudo=1;;
  1896.     esac
  1897.  
  1898.     if [ "$needsudo" ]; then
  1899.         if have sr; then
  1900.             sudo=sr
  1901.         elif have sudo; then
  1902.             sudo=sudo
  1903.         fi
  1904.     fi
  1905.  
  1906.     eval2 ${needsudo:+$sudo} tail -F "$@" "$logfile"
  1907. }
  1908.  
  1909. # dialog_menutag
  1910. #
  1911. # Obtain the menutag chosen by the user from the most recently displayed
  1912. # dialog(1) (or bsddialog(1)) menu and clean up any temporary files.
  1913. #
  1914. # NB: Requires quietly() -- from this file
  1915. # NB: Requires $DIALOG_TMPDIR -- from this file
  1916. # NB: Requires rm(1) -- from base system
  1917. #
  1918. quietly unalias dialog_menutag
  1919. dialog_menutag()
  1920. {
  1921.     local tmpfile="$DIALOG_TMPDIR/dialog.menu.$$"
  1922.  
  1923.     [ -f "$tmpfile" ] || return ${FAILURE:-1}
  1924.  
  1925.     cat "$tmpfile" 2> /dev/null
  1926.     quietly rm -f "$tmpfile"
  1927.  
  1928.     return ${SUCCESS:-0}
  1929. }
  1930.  
  1931. # dialog_menutag2item $tag_chosen $tag1 $item1 $tag2 $item2 ...
  1932. #
  1933. # To use the `--menu' option of dialog(1) (or bsddialog(1)) you must pass an
  1934. # ordered list of tag/item pairs on the command-line. When the user selects a
  1935. # menu option the tag for that item is printed to stderr.
  1936. #
  1937. # This function allows you to dereference the tag chosen by the user back into
  1938. # the item associated with said tag.
  1939. #
  1940. # Pass the tag chosen by the user as the first argument, followed by the
  1941. # ordered list of tag/item pairs (HINT: use the same tag/item list as was
  1942. # passed to dialog(1) or bsddialog(1) for consistency).
  1943. #
  1944. # If the tag cannot be found, NULL is returned.
  1945. #
  1946. quietly unalias dialog_menutag2item
  1947. dialog_menutag2item()
  1948. {
  1949.     local tag="$1" tagn item
  1950.     shift 1
  1951.  
  1952.     while [ $# -gt 0 ]; do
  1953.         tagn="$1"
  1954.         item="$2"
  1955.         shift 2
  1956.  
  1957.         if [ "$tag" = "$tagn" ]; then
  1958.             echo "$item"
  1959.             return ${SUCCESS:-0}
  1960.         fi
  1961.     done
  1962.     return ${FAILURE:-1}
  1963. }
  1964.  
  1965. # dialog_menutag2help $tag_chosen $tag1 $item1 $help1 \
  1966. #                                   $tag2 $item2 $help2
  1967. #
  1968. # To use the `--menu' option of dialog(1) (or bsddialog(1)) with the
  1969. # `--item-help' option, you must pass an ordered list of tag/item/help triplets
  1970. # on the command-line. When the user selects a menu option the tag for that
  1971. # item is printed to stderr.
  1972. #
  1973. # This function allows you to dereference the tag chosen by the user back into
  1974. # the help associated with said tag (item is discarded/ignored).
  1975. #
  1976. # Pass the tag chosen by the user as the first argument, followed by the
  1977. # ordered list of tag/item/help triplets (HINT: use the same tag/item/help list
  1978. # as was passed to dialog(1) or bsddialog(1) for consistency).
  1979. #
  1980. # If the tag cannot be found, NULL is returned.
  1981. #
  1982. dialog_menutag2help()
  1983. {
  1984.     local tag="$1" tagn help
  1985.     shift 1 # tag
  1986.  
  1987.     while [ $# -gt 0 ]; do
  1988.         tagn="$1"
  1989.         help="$3"
  1990.         shift 3 # tagn/item/help
  1991.  
  1992.         if [ "$tag" = "$tagn" ]; then
  1993.             echo "$help"
  1994.             return ${SUCCESS:-0}
  1995.         fi
  1996.     done
  1997.     return ${FAILURE:-1}
  1998. }
  1999.  
  2000. # cvspicker
  2001. #
  2002. # Display a menu of CVS servers to which you have access to. Selecting an entry
  2003. # configures your environment for access to said CVS server.
  2004. #
  2005. # NB: Requires dialog_menutag() dialog_menutag2help() -- from this file
  2006. # NB: Requires $CVSPICKER_EXPORTS $DIALOG_MENU_TAGS -- from this file
  2007. # NB: Requires awk(1) dialog(1) or bsddialog(1) -- from base system
  2008. #
  2009. quietly unalias cvspicker
  2010. cvspicker()
  2011. {
  2012.     local dialog=dialog
  2013.  
  2014.     ! have "$dialog" && have bsddialog && dialog=bsddialog
  2015.  
  2016.     if ! have "$dialog"; then
  2017.         echo "$CVSPICKER_EXPORTS"
  2018.         return ${FAILURE:-1}
  2019.     fi
  2020.     local menu_list
  2021.     menu_list=$(
  2022.         echo "$CVSPICKER_EXPORTS" |
  2023.         awk -v tags="$DIALOG_MENU_TAGS" '
  2024.         !/^[[:space:]]*(#|$)/ {
  2025.             if (++tagn > length(tags)) exit
  2026.             sub(/^[[:space:]]*/, "")
  2027.             sub(/[[:space:]]*$/, "")
  2028.             printf "'\''%s'\'' '\''%s'\''\n",
  2029.                    substr(tags, tagn, 1), $0
  2030.         }'
  2031.     )
  2032.  
  2033.     eval $dialog \
  2034.         --clear --title "'CVSPicker'" \
  2035.         --menu "'Pick a CVS_RSH/CVSROOT pair:'" 17 55 9 \
  2036.         $menu_list \
  2037.         2> "$DIALOG_TMPDIR/dialog.menu.$$"
  2038.     local retval=$?
  2039.  
  2040.     # Return if "Cancel" was chosen (-1) or ESC was pressed (255)
  2041.     [ $retval -eq ${SUCCESS:-0} ] || return $retval
  2042.  
  2043.     local tag="$( dialog_menutag )"
  2044.     eval2 export $( eval dialog_menutag2item "'$tag'" $menu_list )
  2045. }
  2046.  
  2047. # hgrep ...
  2048. #
  2049. # Use in-place of grep(1) whenever you want to preserve the first line of
  2050. # output (often the header when viewing output from ps(1), lsof(8), df(1),
  2051. # netstat(8), arp(8), lsmod(8), route(8), free(1), and many many others).
  2052. #
  2053. # NB: Requires grep(1) head(1) -- from base system
  2054. #
  2055. quietly unalias hgrep
  2056. hgrep()
  2057. {
  2058.     local timeout=0
  2059.  
  2060.     [ "$BASH_VERSION" ] && timeout=1
  2061.  
  2062.     if [ $# -gt 1 ]; then
  2063.         local arg
  2064.         for arg in "$@"; do
  2065.             [ -f "$arg" ] && head -1 "$arg" && break
  2066.         done
  2067.     else
  2068.     (
  2069.         IFS=;
  2070.         read -r -t $timeout LINE
  2071.         printf "\e[1m%s\e[0m\n" "$LINE"
  2072.     )
  2073.     fi
  2074.  
  2075.     grep "$@"
  2076. }
  2077.  
  2078. # myshopts [OPTIONS]
  2079. #
  2080. # Configures/Displays your desired shopt(1) options. The following environment
  2081. # variables should be configured to enable/disable desired options:
  2082. #
  2083. # Options:
  2084. #   -h   Print this usage statement and exit.
  2085. #   -v   Verbose. Print the state of desired options regardless of
  2086. #        whether their states have changed or not. If passed twice,
  2087. #        (e.g., `-vv' or `-v -v') the values of each variable will
  2088. #        be printed while processing each for options.
  2089. #
  2090. # Environment:
  2091. #   BASH2345_SHOPT_ENABLE
  2092. #   BASH2345_SHOPT_DISABLE
  2093. #       Each line represents a single option, with the first word on
  2094. #       each line representing the option and the remainder of the
  2095. #       line being comments you make up. A line can also be nothing
  2096. #       but a comment if it begins with the pound-sign (#), after any
  2097. #       length of whitespace.
  2098. #
  2099. #       For each option, the option will either be disabled if it is
  2100. #       added to the "*_DISABLE" variable or enabled if added to the
  2101. #       "*_ENABLE" variable.
  2102. #
  2103. #       If a variable is changed from its current state and you are
  2104. #       logged in interactively, a line showing the current state of
  2105. #       each option will be printed.
  2106. #
  2107. #   BASH45_SHOPT_ENABLE
  2108. #   BASH45_SHOPT_ENABLE
  2109. #       These variables are like the above but are for options that
  2110. #       are specific to version 4.x of bash(1). These options will
  2111. #       not be enabled/disabled unless BASH_VERSION is 4.*, prevent-
  2112. #       ing errors about unknown options in older versions of bash.
  2113. #
  2114. # NB: Requires eprintf() myshopts_usage() -- from this file
  2115. # NB: Requires awk(1) -- from base system
  2116. #
  2117. quietly unalias myshopts_usage
  2118. myshopts_usage()
  2119. {
  2120.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  2121.     local optfmt='\t%-4s %s\n'
  2122.     local envfmt='\t%s\t%s\n'
  2123.  
  2124.     eprintf "Usage: %s [OPTIONS]\n" "$FUNCNAME"
  2125.     eprintf "Options:\n"
  2126.     eprintf "$optfmt" "-h" \
  2127.             "Print this usage statement and exit."
  2128.     eprintf "$optfmt" "-v" \
  2129.             "Verbose. Print the state of desired options regardless of"
  2130.     eprintf "$optfmt" "" \
  2131.             "whether their states have changed or not. If passed twice,"
  2132.     eprintf "$optfmt" "" \
  2133.             "(e.g., \`-vv' or \`-v -v') the values of each variable will"
  2134.     eprintf "$optfmt" "" \
  2135.             "be printed while processing each for options."
  2136.  
  2137.     eprintf "\n"
  2138.  
  2139.     eprintf "Environment:\n"
  2140.     eprintf "$envfmt" "BASH2345_SHOPT_ENABLE" ""
  2141.     eprintf "$envfmt" "BASH2345_SHOPT_DISABLE" ""
  2142.     eprintf "$envfmt" "" \
  2143.             "Each line represents a single option, with the first word on"
  2144.     eprintf "$envfmt" "" \
  2145.             "each line representing the option and the remainder of the"
  2146.     eprintf "$envfmt" "" \
  2147.             "line being comments you make up. A line can also be nothing"
  2148.     eprintf "$envfmt" "" \
  2149.             "but a comment if it begins with the pound-sign (#), after any"
  2150.     eprintf "$envfmt" "" \
  2151.             "length of whitespace."
  2152.     eprintf "\n"
  2153.     eprintf "$envfmt" "" \
  2154.             "For each option, the option will either be disabled if it is"
  2155.     eprintf "$envfmt" "" \
  2156.             'added to the "*_DISABLE" variable or enabled if added to the'
  2157.     eprintf "$envfmt" "" \
  2158.             '"*_ENABLE" variable.'
  2159.     eprintf "\n"
  2160.     eprintf "$envfmt" "" \
  2161.             "If a variable is changed from its current state and you are"
  2162.     eprintf "$envfmt" "" \
  2163.             "logged in interactively, a line showing the current state of"
  2164.     eprintf "$envfmt" "" \
  2165.             "each option will be printed."
  2166.     eprintf "\n"
  2167.     eprintf "$envfmt" "BASH45_SHOPT_ENABLE" ""
  2168.     eprintf "$envfmt" "BASH45_SHOPT_DISABLE" ""
  2169.     eprintf "$envfmt" "" \
  2170.             "These variables are like the above but are for options that"
  2171.     eprintf "$envfmt" "" \
  2172.             "are specific to version 4.x of bash(1). These options will"
  2173.     eprintf "$envfmt" "" \
  2174.             "not be enabled/disabled unless BASH_VERSION is 4.*, prevent-"
  2175.     eprintf "$envfmt" "" \
  2176.             "ing errors about unknown options in older versions of bash."
  2177.  
  2178.     return ${FAILURE:-1}
  2179. }
  2180. quietly unalias myshopts
  2181. myshopts()
  2182. {
  2183.     local verbose=
  2184.     local OPTIND flag
  2185.     while getopts hv flag; do
  2186.         case "$flag" in
  2187.         v) verbose=$(( ${verbose:-0} + 1 ));;
  2188.         h|\?) myshopts_usage
  2189.               return ${FAILURE:-1} ;;
  2190.         esac
  2191.     done
  2192.     shift $(( $OPTIND - 1 ))
  2193.  
  2194.     #
  2195.     # Process user-defined environment variables into our options-lists.
  2196.     #
  2197.     local shopt_enable_list="" shopt_disable_list="" options_list var
  2198.     case "$BASH_VERSION" in
  2199.     2.*|3.*|4.*|5.*)
  2200.         #
  2201.         # Bash version 2, 3, or 4 shopt(1) variables to be ENABLED
  2202.         #
  2203.         options_list=$( echo "$BASH2345_SHOPT_ENABLE" |
  2204.                             awk '!/^[[:space:]]*($|#)/{print $1}' )
  2205.         if [ "$options_list" ]; then
  2206.             [ ${verbose:-0} -ge 2 ] &&
  2207.                 eprintf "BASH2345_SHOPT_ENABLE='%s'\n" \
  2208.                         "$BASH2345_SHOPT_ENABLE"
  2209.             for var in $options_list; do
  2210.                 shopt_enable_list="$shopt_enable_list $var"
  2211.             done
  2212.         fi
  2213.  
  2214.         #
  2215.         # Bash version 2, 3, or 4 shopt(1) variables to be DISABLED
  2216.         #
  2217.         options_list=$( echo "$BASH2345_SHOPT_DISABLE" |
  2218.                             awk '!/^[[:space:]]*(#|$)/{print $1}' )
  2219.         if [ "$options_list" ]; then
  2220.             [ ${verbose:-0} -ge 2 ] &&
  2221.                 eprintf "BASH2345_SHOPT_DISABLE='%s'\n" \
  2222.                         "$BASH2345_SHOPT_DISABLE"
  2223.             for var in $options_list; do
  2224.                 shopt_disable_list="$shopt_disable_list $var"
  2225.             done
  2226.         fi
  2227.     esac
  2228.     case "$BASH_VERSION" in
  2229.     4.*|5.*)
  2230.         #
  2231.         # Bash version 4 shopt(1) variables to be ENABLED
  2232.         #
  2233.         options_list=$( echo "$BASH45_SHOPT_ENABLE" |
  2234.                             awk '!/^[[:space:]]*($|#)/{print $1}' )
  2235.         if [ "$options_list" ]; then
  2236.             [ ${verbose:-0} -ge 2 ] &&
  2237.                 eprintf "BASH45_SHOPT_ENABLE='%s'\n" \
  2238.                         "$BASH45_SHOPT_ENABLE"
  2239.             for var in $options_list; do
  2240.                 shopt_enable_list="$shopt_enable_list $var"
  2241.             done
  2242.         fi
  2243.  
  2244.         #
  2245.         # Bash version 4 shopt(1) variables to be DISABLED
  2246.         #
  2247.         options_list=$( echo "$BASH45_SHOPT_DISABLE" |
  2248.                             awk '!/^[[:space:]]*($|#)/{print $1}' )
  2249.         if [ "$options_list" ]; then
  2250.             [ ${verbose:-0} -ge 2 ] &&
  2251.                 eprintf "BASH45_SHOPT_DISABLE='%s'\n" \
  2252.                         "$BASH45_SHOPT_DISABLE"
  2253.             for var in $options_list; do
  2254.                 shopt_disable_list="$shopt_disable_list $var"
  2255.             done
  2256.         fi
  2257.     esac
  2258.  
  2259.     #
  2260.     # Toggle the values of variables controlling optional shell behavior.
  2261.     # NOTE: These will be implicitly ignored for non-interactive sessions
  2262.     # NOTE: Capture the current value for later before changing the value
  2263.     #
  2264.     for var in $shopt_enable_list; do
  2265.         shopt -q $var
  2266.         eval local ${var}_before=$?
  2267.         shopt -s $var
  2268.     done
  2269.     for var in $shopt_disable_list; do
  2270.         shopt -q $var
  2271.         eval local ${var}_before=$?
  2272.         shopt -u $var
  2273.     done
  2274.  
  2275.     #
  2276.     # If we're running interactively (or verbosity is requested), show
  2277.     # which shell options have been enabled/disabled.
  2278.     #
  2279.     if [ "$interactive" -o "$verbose" ]; then
  2280.         for var in $shopt_enable_list $shopt_disable_list; do
  2281.             if [ "$verbose" ]; then
  2282.                 if [ "$LOLCAT" ]; then
  2283.                     shopt $var | $LOLCAT
  2284.                 else
  2285.                     shopt $var
  2286.                 fi
  2287.             else
  2288.                 # Report on values that changed state
  2289.                 shopt -q $var
  2290.                 if ! eval [ \$${var}_before -eq $? ]; then
  2291.                     if [ "$LOLCAT" ]; then
  2292.                         shopt $var | $LOLCAT
  2293.                     else
  2294.                         shopt $var
  2295.                     fi
  2296.                 fi
  2297.             fi
  2298.         done
  2299.     fi
  2300. }
  2301.  
  2302. #
  2303. # CVS functions
  2304. #
  2305. # NB: Requires cvs(1) file(1) find(1) xargs(1) -- from base system
  2306. #
  2307. quietly unalias cvs_admin_binaries
  2308. cvs_admin_binaries()
  2309. {
  2310.     local recursive= undo=
  2311.     local gnu_xargs=
  2312.  
  2313.     case "$UNAME_s" in
  2314.     Linux|CYGWIN*) gnu_xargs=1;;
  2315.     esac
  2316.  
  2317.     local OPTIND flag
  2318.     while getopts ru flag; do
  2319.         case "$flag" in
  2320.         r) recursive=1;;
  2321.         u) undo=1;;
  2322.         esac
  2323.     done
  2324.     shift $(( $OPTIND - 1 ))
  2325.  
  2326.     ( if [ "$recursive" ]; then
  2327.         find . -type f ! -path '*/CVS/*'
  2328.       else
  2329.         find . -mindepth 1 -maxdepth 1 -type f
  2330.       fi
  2331.     ) | (
  2332.         while read file; do
  2333.             filetype=$( file -b "$file" )
  2334.             case "$filetype" in
  2335.             *ICC*|*ELF*|*data*|*font*|*icon*|*image*|*archive*)
  2336.                 echo "$file";;
  2337.             esac
  2338.         done
  2339.     ) | (
  2340.         if [ "$undo" ]; then
  2341.             xargs ${gnu_xargs:+-r} cvs admin -kkv
  2342.         else
  2343.             xargs ${gnu_xargs:+-r} cvs admin -ko
  2344.         fi
  2345.     )
  2346. }
  2347. alias cvs_admin_binaries_undo='cvs_admin_binaries -u'
  2348. quietly unalias cvs_add_recursive
  2349. cvs_add_recursive()
  2350. {
  2351.     local gnu_xargs=
  2352.  
  2353.     case "$UNAME_s" in
  2354.     Linux|CYGWIN*) gnu_xargs=1;;
  2355.     esac
  2356.  
  2357.     ( [ $# -gt 0 ] || set -- .
  2358.       while [ $# -gt 0 ]; do
  2359.         find "$1" -type d
  2360.         shift 1
  2361.       done
  2362.     ) | (
  2363.         while read dir; do
  2364.             # Skip invalid directories
  2365.             case "$dir" in
  2366.             .) continue;;
  2367.             *) [ "${dir##*/}" != "CVS" ] || continue;;
  2368.             esac
  2369.  
  2370.             # Add the directory
  2371.             cvs add "$dir"
  2372.  
  2373.             # Add regular files from this directory
  2374.             find "$dir" -type f -mindepth 1 -maxdepth 1 |
  2375.                 xargs ${gnu_xargs:+-r} cvs add
  2376.         done
  2377.     )
  2378. }
  2379. quietly unalias cvs_rm_recursive
  2380. cvs_rm_recursive()
  2381. {
  2382.     local gnu_xargs=
  2383.  
  2384.     case "$UNAME_s" in
  2385.     Linux|CYGWIN*) gnu_xargs=1;;
  2386.     esac
  2387.  
  2388.     ( [ $# -gt 0 ] || set -- .
  2389.       while [ $# -gt 0 ]; do
  2390.         find "$1" -type d
  2391.         shift 1
  2392.       done
  2393.     ) | (
  2394.         while read dir; do
  2395.             # Skip invalid directories
  2396.             case "$dir" in
  2397.             .) continue;;
  2398.             *) [ "${dir##*/}" != "CVS" ] || continue;;
  2399.             esac
  2400.  
  2401.             # Remove regular files from this directory
  2402.             find "$dir" -type f -mindepth 1 -maxdepth 1 |
  2403.                 xargs ${gnu_xargs:+-r} cvs rm -f
  2404.         done
  2405.     )
  2406. }
  2407.  
  2408. # dirstack2d
  2409. #
  2410. # Create a series of $D# environment variables based on ${DIRSTACK[#]} array
  2411. # items -- for quick[er] access to directories in the stack.
  2412. #
  2413. # NB: Requires awk(1) -- from base system
  2414. #
  2415. quietly unalias dirstack2d
  2416. dirstack2d()
  2417. {
  2418.     # Unset current $D# variables
  2419.     unset $( set | command awk -F= '/^D[[:digit:]]+=/{print $1}' )
  2420.  
  2421.     #
  2422.     # Recreate $D# variables from $DIRSTACK array
  2423.     #
  2424.     local n=0
  2425.     while [ $n -lt ${#DIRSTACK[@]} ]; do
  2426.         eval D$n=\"\${DIRSTACK[$n]}\"
  2427.  
  2428.         # Expand leading ~ to $HOME
  2429.         case "${DIRSTACK[$n]}" in
  2430.         \~|\~/*)
  2431.             eval D$n=\"\${D$n\#?}\"
  2432.             eval D$n=\"\$HOME\$D$n\"
  2433.         esac
  2434.  
  2435.         n=$(( $n + 1 ))
  2436.     done
  2437. }
  2438.  
  2439. # dirstack_wrap builtin [options]
  2440. #
  2441. # Simple wrapper to execute dirstack2d after forking to some builtin.
  2442. #
  2443. # NB: Requires dirstack2d() -- from this file
  2444. #
  2445. quietly unalias dirstack_wrap
  2446. dirstack_wrap()
  2447. {
  2448.     local bi="$1"
  2449.     shift
  2450.     builtin $bi "$@"
  2451.     dirstack2d
  2452. }
  2453.  
  2454. #
  2455. # Dirstack wrapper aliases
  2456. # NB: Requires dirstack_wrap() -- from this file
  2457. #
  2458. alias pushd='dirstack_wrap pushd'
  2459. alias  popd='dirstack_wrap popd'
  2460. alias  dirs='dirstack_wrap dirs'
  2461. alias    cd='dirstack_wrap cd'
  2462.  
  2463. # colorize [-c ANSI] [-e ANSI] pattern
  2464. #
  2465. # Colorize text matching pattern with ANSI sequence (default is `31;1' for red-
  2466. # bold). Non-matching lines are printed as-is.
  2467. #
  2468. # NB: Requires awk(1) -- from base system
  2469. #
  2470. colorize()
  2471. {
  2472.     local OPTIND=1 OPTARG flag
  2473.     local ti=
  2474.     local te=
  2475.  
  2476.     while getopts c:e: flag; do
  2477.         case "$flag" in
  2478.         c) ti="$OPTARG" ;;
  2479.         e) te="$OPTARG" ;;
  2480.         esac
  2481.     done
  2482.     shift $(( $OPTIND - 1 ))
  2483.  
  2484.     awk -v ti="${ti:-31;1}" -v te="${te:-39;22}" -v pattern="$1" '
  2485.         gsub(pattern, "\033[" ti "m&\033[" te "m")||1
  2486.     ' # END-QUOTE
  2487. }
  2488.  
  2489. #
  2490. # Perforce helpers
  2491. #
  2492. # NB: Requires devel/p4 -- from ports collection
  2493. # NB: Requires awk(1) find(1) sed(1) -- from base system
  2494. #
  2495. quietly unalias p4up
  2496. p4up()
  2497. {
  2498.     find "${1:-.}" -not -type d |
  2499.         sed -e 's/%/%25/g;s/@/%40/g;s/#/%23/g;s/\*/%2A/g' |
  2500.         p4 -x - have 2>&1 |
  2501.         awk '/not on client/&&sub(/ - .*/,"")' |
  2502.                 p4 -x - opened 2>&1 |
  2503.                 awk '/not opened on this client/&&sub(/ - .*/,"")' |
  2504.         sed -e 's/%40/@/g;s/%23/#/g;s/%2A/*/g;s/%25/%/g' |
  2505.         sed -e 's/[[:space:]"'\''\\]/\\&/g'
  2506. }
  2507. quietly unalias p4changes2
  2508. p4changes2()
  2509. {
  2510.     local verbose=
  2511.     [ "$1" = "-v" ] && verbose=1 && shift 1
  2512.     [ "$1" ] || return 1
  2513.     local cmd="p4 changes \"//...@>$1,@<=${2:-now}\""
  2514.     [ "$verbose" ] && cmd="$cmd | awk '{system(\"p4 describe -s \" \$2)}'"
  2515.     echo ">>> $cmd" && eval "$cmd"
  2516. }
  2517. quietly unalias p4getrevs
  2518. p4getrevs()
  2519. {
  2520.     local func=p4getrevs OPTIND=1 OPTARG flag
  2521.     local allrevs=1 revs= get_info= quiet=
  2522.     while getopts iqR: flag; do
  2523.         case "$flag" in
  2524.         i) get_info=1 ;;
  2525.         q) quiet=1 ;;
  2526.         R) revs="$OPTARG" allrevs= ;;
  2527.         esac
  2528.     done
  2529.     shift $(( $OPTIND - 1 ))
  2530.     if [ $# -lt 1 ] || ! [ "$revs" -o "$allrevs" ]; then
  2531.         echo "Usage: $func [-i] [-q] [-R rev[,...]] file ..." >&2
  2532.         return ${FAILURE:-1}
  2533.     fi
  2534.     local file p4path change
  2535.     for file in "$@"; do
  2536.         p4path=$( p4 where "$file" | awk '$0 = $1' ) || continue
  2537.         [ "$allrevs" ] && revs=$( p4 filelog "$file" | awk '
  2538.             $1 == "..." && $2 ~ /^#[[:digit:]]+$/ {
  2539.                 revs = substr($2,2) "," revs
  2540.             }
  2541.             END { sub(/,$/,"",revs); print revs }
  2542.         ' )
  2543.         echo -n "$revs" | awk 'gsub(/,/, " ")||1' | xargs -rn1 sh -c '
  2544.             info_getter="$1" file="$2" p4path="$3"
  2545.             get_info="$4" quiet="$5" revnum="$6"
  2546.             output_file="${file##*/}.$revnum"
  2547.             info_file="${output_file}-info"
  2548.             file_url="http://perforce/@@$p4path?rev1=$revnum"
  2549.             have() { type "$@" > /dev/null 2>&1; }
  2550.             get_revision() {
  2551.                 local cmd=:
  2552.                 if have fetch; then
  2553.                     cmd="fetch ${quiet:+-q} -o"
  2554.                 elif have wget; then
  2555.                     cmd="wget ${quiet:+-q} -O"
  2556.                 elif have curl; then
  2557.                     cmd="curl ${quiet:+-s} -o"
  2558.                 fi
  2559.                 eval $cmd \"\$output_file\" \"\$file_url\"
  2560.             }
  2561.             get_info() {
  2562.                 local change
  2563.                 change=$( p4 filelog "$file#$revnum" |
  2564.                     awk "$info_getter" ) || return
  2565.                 p4 describe -s "$change" | awk "
  2566.                     sub(/^\t+/, \"\"),sub(/^\t+/,\"\")||1
  2567.                 " > "$info_file"
  2568.             }
  2569.             [ -e "$output_file" ] || get_revision
  2570.             [ "$get_info" -a ! -e "$info_file" ] && get_info
  2571.         ' /bin/sh '
  2572.             $1$3 == "...change" && $4 ~ /^[[:digit:]]+$/ {
  2573.                 print $4; exit
  2574.             }
  2575.         ' "$file" "$p4path" "$get_info" "$quiet"
  2576.     done
  2577. }
  2578.  
  2579. #
  2580. # Git helpers
  2581. #
  2582. quietly unalias gitup
  2583. gitup()
  2584. {
  2585.     git status "$@" | awk '!/^#?\t([a-z ]+: +)?\.\.\//'
  2586. }
  2587.  
  2588. #
  2589. # route(8) helpers
  2590. #
  2591. routes_awk='
  2592. BEGIN {
  2593.     columns["host"] = 0
  2594.     domain_len = length(domain)
  2595. }
  2596. !/^[[:space:]]*(#|$)/ &&
  2597.     match($0, /^[^[:space:]]+[[:space:]]+[^[:space:]]/) &&
  2598.     n = split(substr($0, RSTART + RLENGTH - 1), hosts) &&
  2599. 1 {
  2600.     addr = $1
  2601.     for (i = 1; i <= n; i++)
  2602.     {
  2603.         host = hosts[i]
  2604.         host_len = length(host)
  2605.         if (host_len <= domain_len) next
  2606.         host_domain = substr(host, host_len - domain_len + 1)
  2607.         if (host_domain != domain) next
  2608.  
  2609.         short_host_len = host_len - domain_len
  2610.         if (short_host_len > columns["host"])
  2611.             columns["host"] = short_host_len
  2612.         cmd = sprintf("%s route %s %s %s 2>&1",
  2613.             sudo, route_action, addr, route_args)
  2614.         output = ""
  2615.         lines  = 0
  2616.         while (cmd | getline input) {
  2617.             lines++
  2618.             output = sprintf("%s%s%s",
  2619.                 output, output ? "\n" : "", input)
  2620.         }
  2621.         close(cmd)
  2622.         short_hosts[addr] = substr(host, 1, short_host_len)
  2623.         full_hosts[addr] = host
  2624.         cmd_output[addr] = output
  2625.         cmd_lines[addr] = lines
  2626.         next
  2627.     }
  2628. }
  2629. END {
  2630.     for (addr in cmd_output) {
  2631.         short_host = short_hosts[addr]
  2632.         host = full_hosts[addr]
  2633.         output = cmd_output[addr]
  2634.         lines = cmd_lines[addr]
  2635.         if (lines <= 1) {
  2636.             sub(/^[[:space:]]*/, "", output)
  2637.             printf "%-*s => %s\n", columns["host"],
  2638.                 short_host, output
  2639.         } else {
  2640.             printf "%s:\n", host
  2641.             gsub(/\n/, "&\t", output)
  2642.             printf "\t%s\n", output
  2643.         }
  2644.     }
  2645. }
  2646. '
  2647. routes()
  2648. {
  2649.     [ "$ZSH_NAME" ] && local FUNCNAME="$funcstack[1]"
  2650.     local usage="$FUNCNAME %s {add|up|down|delete|reload|show|get}\n"
  2651.     local hosts_file="${ETC_HOSTS:-${HOSTS:-/etc/hosts}}"
  2652.     local name="$1" action="$2" _name domain route_args
  2653.     [ "$name" -a "$action" ] || {
  2654.         printf "Usage: $usage" "${name:-name}" >&2
  2655.         return $FAILURE
  2656.     }
  2657.     _name=$( echo "${name%%[!a-zA-Z0-9_]*}" | tr '[:lower:]' '[:upper:]' )
  2658.     eval routes=\"\$ROUTES_$_name\"
  2659.     [ "$routes" ] || {
  2660.         printf "%s:%u: variable ROUTES_%s unset or NULL!\n" \
  2661.             "$FUNCNAME" "$LINENO" "$_name" >&2
  2662.         return $FAILURE
  2663.     }
  2664.     read domain route_args <<-EOF
  2665.     $routes
  2666.     EOF
  2667.     case "$action" in
  2668.     [Uu][Pp]|[Aa][Dd][Dd])
  2669.         awk -v sudo="sr" \
  2670.             -v route_action="add" -v route_args="$route_args" \
  2671.             -v domain="$domain" "$routes_awk" "$hosts_file" ;;
  2672.     [Dd][Oo][Ww][Nn]|[Dd][Ee][Ll][Ee][Tt][Ee])
  2673.         awk -v sudo="sr" -v route_action="delete" -v route_args="" \
  2674.             -v domain="$domain" "$routes_awk" "$hosts_file" ;;
  2675.     [Rr][Ee][Ll][Oo][Aa][Dd])
  2676.         $FUNCNAME $_name down && $FUNCNAME $_name up ;;
  2677.     [Ss][Hh][Oo][Ww]|[Gg][Ee][Tt])
  2678.         awk -v route_action="-nv get" -v route_args="| tail -1" \
  2679.             -v domain="$domain" "$routes_awk" "$hosts_file" ;;
  2680.     *)
  2681.         printf "Usage: $usage" "${name:-name}" >&2
  2682.         return $FAILURE
  2683.     esac
  2684. }
  2685.  
  2686. ############################################################ SHELL BEHAVIOR
  2687.  
  2688. #
  2689. # Set prompt style
  2690. #
  2691. case "$HOSTNAME" in
  2692. *.*.*.*) export HOSTID="${HOSTNAME%.*.*}" ;;
  2693. *.*.*) export HOSTID="${HOSTNAME%%.*}" ;;
  2694. *) export HOSTID="$HOSTNAME"
  2695. esac
  2696. if [ "$ZSH_NAME" ]; then
  2697.     export PS1=$'\e[1m'"%F{green}$USER@$HOSTID %F{blue}%~ %#%f "$'\e[22m'
  2698. else
  2699.     export PS1='\[\e[32;1m\]$USER@$HOSTID \[\e[34m\]\W \$\[\e[0m\] '
  2700. fi
  2701. [ "$interactive" ] && PROMPT_COMMAND="$LOLEXEC"
  2702.  
  2703. #
  2704. # lolcat integration
  2705. #
  2706. have lolcat && LOLCAT=lolcat
  2707.  
  2708. #
  2709. # If we became root via sudo(8), preserve $HOME
  2710. #
  2711. [ "$SUDO_USER" != "root" ] && export HOME="$( eval echo ~$SUDO_USER )"
  2712.  
  2713. #
  2714. # Set the window title for terminals such as "xterm", "rxvt", and others
  2715. #
  2716. [ "$interactive" ] \
  2717.     && [ "$TERM" != "linux" ] \
  2718.     && [ "$TERM" != "cons25" ] \
  2719.     && settitle "$USER@${HOSTNAME%.*.*}" "${PWD/#$HOME/~}"
  2720.  
  2721. #
  2722. # Fixup $PATH
  2723. #
  2724. path_munge -r "$HOME/bin"
  2725. path_munge -p "$HOME/Desktop/bin" "$HOME/bin"
  2726. path_munge /sbin /usr/sbin /usr/local/sbin /usr/games
  2727. path_munge "$HOME/.local/bin"
  2728.  
  2729. # Fixup $PATH on Mac OS X Lion
  2730. [ -d "/Developer/usr/bin" ] && path_munge /Developer/usr/bin
  2731.  
  2732. # Latest Apple Developer Tools move cvs once-again, this time
  2733. # XCode 4.3.1 places cvs inside itself -- March 17th, 2012
  2734. [ -f "/Applications/Xcode.app/Contents/Developer/usr/bin/cvs" ] &&
  2735.     path_munge /Applications/Xcode.app/Contents/Developer/usr/bin
  2736.  
  2737. #
  2738. # Make new files group-writable by default
  2739. #
  2740. umask 002
  2741.  
  2742. #
  2743. # shopt(1) options to enable/disable.
  2744. #
  2745. BASH2345_SHOPT_ENABLE='
  2746.     cdspell        inline correction of minor errors in cd
  2747.     checkwinsize   live tracking of $COLUMNS and $LINES
  2748.     histreedit     editing of a failed history expansion
  2749.     histverify     inline history expansion
  2750. '
  2751. BASH2345_SHOPT_DISABLE='
  2752.     # none to report at this time
  2753. '
  2754. BASH45_SHOPT_ENABLE='
  2755.     dirspell     directory spell correction on tab-completion
  2756. '
  2757. BASH45_SHOPT_DISABLE='
  2758.     # none to report at this time
  2759. '
  2760. myshopts # see `myshopts -h'
  2761.  
  2762. ############################################################ ALIASES
  2763.  
  2764. # timecat
  2765. #
  2766. # Used for timing adhoc duties or timing cat operations.
  2767. #
  2768. alias tc="time cat"
  2769. alias timecat="time cat"
  2770.  
  2771. # stuff | dim
  2772. #
  2773. # Make stdout appear "dimmed" in the terminal, allowing errors to stand out.
  2774. #
  2775. alias dim="sed -e s/^/$'\e'[2m/\;s/\$/$'\e'[0m/"
  2776.  
  2777. #
  2778. # zlog_wrapper aliases (see zlog_wrapper in FUNCTIONS above)
  2779. #
  2780. # !!!the below usage statement is generated from zlog_usage above!!!
  2781. # Usage: ALIAS [OPTIONS] [PATTERN]
  2782. # Arguments:
  2783. #   PATTERN    Awk(1) regular expression pattern to search logfile for.
  2784. #
  2785. # Options:
  2786. #   -h         Print this usage statement and exit.
  2787. #   -v         Verbose. Show individual matching lines.
  2788. #   -d1,2,3    Comma-separated list of field numbers to display as the
  2789. #              date/time when providing summary output (ignored if `-v'
  2790. #              is passed). Default is 1,2,3. A value of `NF' prints the
  2791. #              entire line.
  2792. #
  2793. alias messages='zlog_wrapper messages "$MESSAGES"'
  2794. alias aelog='zlog_wrapper aelog "$APACHE_ERROR_LOG" -d1,2,3,4,5'
  2795. alias aalog='zlog_wrapper aalog "$APACHE_ACCESS_LOG" -d4,5,1'
  2796. alias aelog_sa='zlog_wrapper aelog_sa "$APACHE_ERROR_LOG_SA" -d1,2,3,4,5'
  2797. alias aalog_sa='zlog_wrapper aalog_sa "$APACHE_ACCESS_LOG_SA" -d4,5,1'
  2798. alias aselog='zlog_wrapper aselog "$APACHE_SSL_ERROR_LOG" -d1,2,3,4,5'
  2799. alias asalog='zlog_wrapper asalog "$APACHE_SSL_ACCESS_LOG" -d4,5,1'
  2800.  
  2801. #
  2802. # tlog aliases (see tlog in FUNCTIONS above)
  2803. #
  2804. # Usage: ALIAS [OPTIONS]
  2805. # Options are sent to tail(1).
  2806. #
  2807. alias tm='tlog "$MESSAGES"'
  2808. alias tael='tlog "$APACHE_ERROR_LOG"'
  2809. alias taal='tlog "$APACHE_ACCESS_LOG"'
  2810. alias tael_sa='tlog "$APACHE_ERROR_LOG_SA"'
  2811. alias taal_sa='tlog "$APACHE_ACCESS_LOG_SA"'
  2812. alias tasel='tlog "$APACHE_SSL_ERROR_LOG"'
  2813. alias tasal='tlog "$APACHE_SSL_ACCESS_LOG"'
  2814.  
  2815. #
  2816. # Random keepalive [ka] alias (based on system-availability of various
  2817. # fun utilities).
  2818. #
  2819. if [ "$BASH_VERSION" ]; then
  2820. declare -a ka=()
  2821. have worms   && ka[${#ka[@]}]="worms -d 25 | ${LOLCAT:-cat}"
  2822. have rain    && ka[${#ka[@]}]="rain -d 50 | ${LOLCAT:-cat}"
  2823. case "$LOLCAT" in
  2824. *lolcat) have grdc && ka[${#ka[@]}]="grdc | $LOLCAT -a" ;;
  2825. *) have grdc && ka[${#ka[@]}]="grdc | ${LOLCAT:-cat}"
  2826. esac
  2827. have fortune && ka[${#ka[@]}]="
  2828.     ( stty -kerninfo
  2829.       trap 'kill -9 \$sleeppid' SIGINFO
  2830.       trap exit SIGINT
  2831.       while :;do
  2832.         case \"\$LOLCAT\" in
  2833.         *lolcat) fortune freebsd-tips |
  2834.             sed -e 's/^[[:space:]]\{1,\}/ /' | \$LOLCAT -a ;;
  2835.         *) fortune freebsd-tips | \${LOLCAT:-cat}
  2836.         esac
  2837.         sleep 80 & sleeppid=\$!
  2838.         wait \$sleeppid
  2839.         echo --
  2840.       done
  2841.     ) 2> /dev/null"
  2842. have cmatrix && ka[${#ka[@]}]="cmatrix -r"
  2843. have cbonsai && ka[${#ka[@]}]="cbonsai -S -p -m \"\$( fortune freebsd-tips )\""
  2844. have asciiquarium && ka[${#ka[@]}]="asciiquarium"
  2845. if have pipes.sh; then
  2846.     ka[${#ka[@]}]="pipes.sh"
  2847.     ka[${#ka[@]}]="pipes.sh -p 3 -t 8 -t 9 -c 1" # Railways
  2848. fi
  2849. [ ${#ka[@]} -gt 0 ] || ka[0]="while :;do echo -n .;sleep 80;done"
  2850. alias ka='eval "${ka[$(($RANDOM/(32769/${#ka[@]})))]}"'
  2851. fi
  2852.  
  2853. #
  2854. # dbcat alias for reading Berkeley DB database files (based on system-
  2855. # availability of standard utilities).
  2856. #
  2857. dbutil=false
  2858. dbflags=
  2859. if have "db_dump"; then
  2860.     # RHEL/CentOS/Cygwin
  2861.     dbutil="db_dump"
  2862.     db185util="db_dump185"
  2863.     dbflags="-p"
  2864. elif have "db_dump-4.6"; then
  2865.     # FreeBSD-8.x
  2866.     dbutil="db_dump-4.6"
  2867.     db185util="db_dump185-4.6"
  2868.     dbflags="-p"
  2869. elif have "db_dump-4.2"; then
  2870.     # FreeBSD-4.11
  2871.     dbutil="db_dump-4.2"
  2872.     db185util="db_dump185-4.2"
  2873.     dbflags="-p"
  2874. elif have "db3_dump"; then
  2875.     # FreeBSD-4.8
  2876.     dbutil="db3_dump"
  2877.     db185util="db3_dump185"
  2878.     dbflags="-p"
  2879. elif have "db"; then
  2880.     # Legacy
  2881.     dbutil="db"
  2882. fi
  2883. alias dbcat="/bin/sh -c '"'
  2884.     while [ $# -gt 0 ]; do
  2885.         dbfile="$1"
  2886.         shift
  2887.         type=$( file "$dbfile" ) || continue
  2888.         echo "$type" | awk \
  2889.             -v dbfile="$dbfile" \
  2890.             -v dbutil="'"$dbutil"'" \
  2891.             -v db185util="'"$db185util"'" \
  2892.             -v dbflags="'"$dbflags${dbflags:+ }"'" \
  2893.         '\'\\\'\''
  2894.             BEGIN { isdb = 0 }
  2895.             /: Berkeley DB / \
  2896.             {
  2897.                 isdb = 1
  2898.                 if ( dbutil == "db" ) {
  2899.                     sub(/.*\(/, "")
  2900.                     sub(/,.*/, "")
  2901.                     dbutil = dbutil " " tolower($0)
  2902.                 }
  2903.                 else if ( $0 ~ /1.8[45]/ )
  2904.                     dbutil = db185util
  2905.                 system(dbutil " " dbflags dbfile)
  2906.             }
  2907.             END { exit ! isdb }
  2908.         '\'\\\'\''
  2909.     done'\'" -- /bin/sh"
  2910.  
  2911. #
  2912. # Alias for becoming root while maintaining shell customizations.
  2913. #
  2914. if have sr; then
  2915.     flags=
  2916.     sr=$( which sr 2> /dev/null )
  2917.     if [ -L "$sr" ]; then
  2918.         if have readlink; then
  2919.             sr=$( readlink -f "$sr" )
  2920.         elif have realpath; then
  2921.             sr=$( realpath "$sr" )
  2922.         elif have perl; then
  2923.             sr=$( perl -le '
  2924.                 use Cwd;
  2925.                 print Cwd::abs_path(@ARGV);
  2926.             ' -- "$sr" )
  2927.         fi
  2928.         [ "${sr##*/}" = sudo ] && flags="-E"
  2929.     fi
  2930.     alias srsu="sr $flags env $SHELL --rcfile $HOME/.bash_profile"
  2931. elif have sudo; then
  2932.     alias srsu="sudo -E env $SHELL --rcfile $HOME/.bash_profile"
  2933. elif have su; then
  2934.     alias srsu="su -m root --rcfile $HOME/.bash_profile"
  2935. fi
  2936.  
  2937. #
  2938. # Editor settings (in order of preference)
  2939. #
  2940. if have vim; then
  2941.     export EDITOR=vim
  2942.     alias vi='vim'
  2943. elif have vi; then
  2944.     export EDITOR=vi
  2945. elif have ee; then
  2946.     export EDITOR=ee
  2947. elif have nano; then
  2948.     export EDITOR=nano
  2949. elif have pico; then
  2950.     export EDITOR=pico
  2951. elif have emacs; then
  2952.     export EDITOR=emacs
  2953. fi
  2954. alias edit="$EDITOR"
  2955.  
  2956. #
  2957. # Alias for editing a file as root maintaining vi customizations
  2958. #
  2959. if have sr; then
  2960.     alias srvi='sr env HOME="$HOME" $EDITOR'
  2961. elif have sudo; then
  2962.     alias srvi='sudo env HOME="$HOME" $EDITOR'
  2963. fi
  2964.  
  2965. #
  2966. # Alias for machines without sr
  2967. #
  2968. have sr || alias sr="sudo"
  2969.  
  2970. #
  2971. # Forthisms
  2972. #
  2973. # I was spending a lot of time in Forth while writing loader_menu for FreeBSD,
  2974. # and couldn't stop myself from using these to no-end of pain. So I decided to
  2975. # add the below to ease my pain.
  2976. #
  2977. alias .s="ls"
  2978.  
  2979. #
  2980. # View man(1) pages with vim(1)
  2981. #
  2982. have vim && alias man="man -P \"sh -c 'col -b | vim -c \\\"set ft=man nomod nolist\\\" -'\""
  2983.  
  2984. #
  2985. # View man(1) pages with lolcat
  2986. #
  2987. have lolcat && alias lolman="man -P 'col -b | lolcat -f | less -R'"
  2988.  
  2989. #
  2990. # diff-specific vim(1) alias
  2991. #
  2992. quietly unalias dview
  2993. alias dview="vim +/'^\\(Index\\|diff\\|--\\|@@\\|====\\).*' +'set hls' +'set syntax=diff' -R"
  2994.  
  2995. #
  2996. # diff-specific
  2997. #
  2998. alias dsumm="awk '"'/^(---|\+\+\+) /{next}/^-/{p++}/^+/{m++}END{printf "-%u/+%u\n",p,m}'\'
  2999.  
  3000. #
  3001. # View ps(1) output with vim(1)
  3002. #
  3003. __ps_args=
  3004. case "$UNAME_s" in
  3005. FreeBSD) __ps_args=auxwwd ;;
  3006. Darwin) __ps_args=auxww ;;
  3007. Linux) __ps_args=auxwwf ;;
  3008. esac
  3009. quietly unalias pview
  3010. alias pview="ps $__ps_args | vim +'hi clear overlength' +'set nowrap hls is' -R -"
  3011. unset __ps_args
  3012.  
  3013. #
  3014. # Abbreviations
  3015. #
  3016. alias b=basename
  3017. alias d=date
  3018. alias di='dirs -v'
  3019. alias h=history
  3020. alias j=jobs
  3021. alias la='ls -al'
  3022. alias ll='ls -l'
  3023. alias lt='ls -Altr'
  3024. alias pd=pushd
  3025. alias po=popd
  3026. alias z=suspend
  3027. alias bx=BitchX
  3028.  
  3029. #
  3030. # OS-specific Aliases/functions (until they can be generalized)
  3031. #
  3032. case "$UNAME_s" in
  3033. Linux|CYGWIN*)
  3034.     #
  3035.     # Force sort(1) to NOT ignore leading dots
  3036.     # NB: Is Linux brain-dead? or just high on crack?
  3037.     #
  3038.     export LC_COLLATE=C
  3039.  
  3040.     #
  3041.     # Make ls(1) colorful (customized by $HOME/.dir_colors)
  3042.     #
  3043.     alias ls='ls --color=tty -ACF'
  3044.  
  3045.     #
  3046.     # X-related aliases
  3047.     #
  3048.     alias Xsession="/etc/X11/xdm/Xsession"
  3049.     alias xsession="Xsession"
  3050.  
  3051.     #
  3052.     # ps(1) related
  3053.     #
  3054.     pst()
  3055.     {
  3056.         ps axo lstart,pid,ppid,uid,tt,stat,time,command "$@" | awk '
  3057.         BEGIN {
  3058.             getline
  3059.             match($0, /.*STARTED/)
  3060.             print "   STARTED", substr($0, RSTART + RLENGTH)
  3061.         }
  3062.         {
  3063.             date = substr($0, 0, RLENGTH)
  3064.             (cmd = "date -d \"" date "\" +%s") | getline sec
  3065.             close(cmd)
  3066.             printf "%-10s %s\n", sec, substr($0, RLENGTH + 1)
  3067.         }'
  3068.     }
  3069.  
  3070.     vmstat1()
  3071.     {
  3072.         vmstat 1 | awk '/^procs/{printf "%5s %33s %9s %11s %11s %s\n", "-" (procs = $1), "---------" (memory = $2), (swap = $3), "--" (io = $4), "----" (systm = $5), "--" (cpu = $6);next}{printf "%3s %2s %7s %9s %8s %9s %4s %4s %6s %6s %6s %6s %2s %2s %3s %2s %3s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17}'
  3073.     }
  3074.     ;;
  3075. FreeBSD|Darwin)
  3076.     #
  3077.     # boottime: Prints the date/time (format based on current locale)
  3078.     #           that the system booted (resolution is 1-second).
  3079.     # bootsec:  Prints the number of seconds since the epoch (see `%s'
  3080.     #           format in date(1)) that was recorded during boot,
  3081.     #           allowing you to use the `-r seconds' syntax of date(1)
  3082.     #           to represent the boottime in any desired format.
  3083.     #
  3084.     kbt="sysctl kern.boottime"
  3085.     alias boottime="$kbt | sed -e 's/.*} //'"
  3086.     alias bootsec="$kbt | sed -e 's/.* sec = \([0-9]\{1,\}\).*/\1/'"
  3087.     unset kbt
  3088.  
  3089.     #
  3090.     # bootfile: Prints the path to the running kernel.
  3091.     #
  3092.     alias bootfile="sysctl -n kern.bootfile"
  3093.  
  3094.     #
  3095.     # Make ls(1) colorful (customized by $LSCOLORS -- see ls(1))
  3096.     #
  3097.     alias ls="ls -AGCF"
  3098.     export LSCOLORS="Gxfxcxdxbxegedabagacad"
  3099.  
  3100.     #
  3101.     # X-related aliases
  3102.     #
  3103.     alias Xsession="/usr/X11R6/lib/X11/xdm/Xsession"
  3104.     alias xsession="Xsession"
  3105.  
  3106.     #
  3107.     # ps(1) related
  3108.     #
  3109.     pst()
  3110.     {
  3111.         ps axo lstart,pid,ppid,uid,tt,stat,time,command "$@" | awk '
  3112.         BEGIN {
  3113.             (cmd = "date +%c") | getline cdate
  3114.             clen = length(cdate)
  3115.             close(cmd)
  3116.         }
  3117.         !/^-/ {
  3118.             if ($1 != (sdate = "STARTED"))
  3119.             {
  3120.                 cdate = substr($0, 0, clen)
  3121.                 cmd = "date -j -f %c \"" cdate "\" +%s"
  3122.                 cmd | getline sdate
  3123.                 close(cmd)
  3124.             }
  3125.             printf "%-10s %s\n", sdate, substr($0, clen + 1)
  3126.         }'
  3127.     }
  3128.     ;;
  3129. esac
  3130.  
  3131. #
  3132. # ssh(1) helpers
  3133. #
  3134. alias sshk="ssh -t vm11 . .bash_profile '&&' ssh -At eskarina ssh -At localhost ssh -A"
  3135. alias sad="\ssh-agent-dup"
  3136.  
  3137. ############################################################ COMPLETION
  3138.  
  3139. _ssh()
  3140. {
  3141.     local file files=
  3142.     for file in \
  3143.         ~/.ssh/config ~/.ssh/config.d/* \
  3144.         ~/.ssh/known_hosts /etc/ssh/known_hosts \
  3145.     ; do [ -e "$file" ] && files="$files $file"; done
  3146.     [ ! "$files" ] || COMPREPLY=( $( compgen -W "$( awk '
  3147.         FILENAME ~ /config/ && tolower($1) == "host" {
  3148.             for (n = 2; n <= NF; n++) if ($n !~ /[?*]/) print $n
  3149.         }
  3150.         FILENAME ~ /hosts/ {
  3151.             for (n = split($1, hosts, /,/); n > 0; n--) {
  3152.                 if ((len = length(hosts[n])) < 1) continue
  3153.                 if ((host = hosts[n]) ~ /^\[.*\]$/)
  3154.                     host = substr(host, 2, len - 2)
  3155.                 print host
  3156.             }
  3157.         }
  3158.     ' $files 2> /dev/null )" -- ${COMP_WORDS[COMP_CWORD]} ) ) || : ok
  3159. }
  3160. [ "$ZSH_NAME" ] || complete -F _ssh ssh
  3161.  
  3162. ############################################################ MISCELLANEOUS
  3163.  
  3164. #
  3165. # cvs(1) settings
  3166. #
  3167. export CVS_RSH=ssh CVSROOT=cvs.vicor.com:/repos/projects
  3168.  
  3169. #
  3170. # BitchX(1) settings
  3171. #
  3172. export IRCNICK=dteske
  3173. #export IRCSERVER=frenode.net
  3174. export IRCSERVER=irc.prison.net
  3175. export IRCNAME=dteske
  3176.  
  3177. #
  3178. # jail_build(8) settings
  3179. #
  3180. export JAIL_BUILD_DESTDIR=/raid1/jails
  3181.  
  3182. #
  3183. # Override the default password prompt for sudo(8). This helps differentiate
  3184. # the sudo(8) password prompt from others such as su(1), ssh(1), and login(1).
  3185. #
  3186. export SUDO_PROMPT='[sudo] Password:'
  3187.  
  3188. #
  3189. # Manual pages with color
  3190. #
  3191. export LESS_TERMCAP_mb=$'\e[31m'      # turn on blinking
  3192. export LESS_TERMCAP_md=$'\e[31m'      # turn on bold (extra bright)
  3193. export LESS_TERMCAP_me=$'\e[m'        # turn off all attributes
  3194. export LESS_TERMCAP_so=$'\e[1;33;44m' # begin standout mode
  3195. export LESS_TERMCAP_se=$'\e[m'        # exit standout mode
  3196. export LESS_TERMCAP_us=$'\e[1;34m'    # begin underline mode
  3197. export LESS_TERMCAP_ue=$'\e[m'        # exit underline mode
  3198.  
  3199. #
  3200. # Quietly attach to running ssh-agent(1) unless agent already given
  3201. #
  3202. if [ ! "$SSH_AUTH_SOCK" ]; then
  3203.     if [ "$interactive" ]; then
  3204.         ssh-agent-dup
  3205.     else
  3206.         quietly ssh-agent-dup -n || :
  3207.     fi
  3208. fi
  3209.  
  3210. ################################################################################
  3211. # END
  3212. ################################################################################
Advertisement
Add Comment
Please, Sign In to add comment