├── .gitignore ├── .inputrc ├── README.md ├── cyg-wrapper.sh ├── forward_completion.sh ├── install.sh ├── list_threads.sh ├── munge.bashrc ├── nm_n_grep.sh ├── push.bashrc └── ssh.bashrc /.gitignore: -------------------------------------------------------------------------------- 1 | .*sw* 2 | -------------------------------------------------------------------------------- /.inputrc: -------------------------------------------------------------------------------- 1 | # To source this file: 2 | # bind -f {thefilename} 3 | # To know the list of functions, bound or not 4 | # bind -p | less 5 | 6 | # Deserve to be know 7 | # - "\C-x\C-u": undo 8 | # - "\e#": insert-comment 9 | # - "\C-s": forward-search-history 10 | # - "\C-r": reverse-search-history 11 | # - "\et": transpose-words 12 | # - restore a binding: self-insert 13 | 14 | # Don't beep 15 | set bell-style none 16 | 17 | # enable 8-bits characters ... 18 | set meta-flag on 19 | set convert-meta off 20 | set output-meta on 21 | 22 | # clear a line. 23 | #Control-u: kill-whole-line 24 | #Home: beginning-of-line 25 | 26 | # Moving around 27 | "\e[1;5C": forward-word 28 | "\e[1;5D": backward-word 29 | 30 | # Ctrl+Backspace/Delete to delete whole words 31 | "\e[3;5~": kill-word 32 | "\C-_": backward-kill-word 33 | 34 | # Ctrl+Shift+Backspace/Delete to delete to start/end of the line 35 | "\e[3;6~": kill-line 36 | "\xC2\x9F": backward-kill-line # for UTF-8 37 | #"\x9F": backward-kill-line # for ISO-8859-x 38 | #"\e\C-_": backward-kill-line # for any other charset 39 | 40 | # Insert "$()" around current line 41 | "\e\C-m": '\C-a"$(\C-e)"' 42 | 43 | # CTRL+up/down: navigate search history 44 | "\e[1;5A": history-search-backward 45 | "\e[1;5B": history-search-forward 46 | 47 | # Insert " 2>&1" 48 | "\e2": '2>&1' 49 | # Append " | less" 50 | "\el": '\C-e | less' 51 | # Prepend "less" 52 | "\eL": '\C-aless ' 53 | # Find 54 | "\eF": '\C-afind . -name ' 55 | # append "| awk /pattern/ {print $42}" 56 | "\ea": '\C-e | awk \'/pattern/ {print $42}\'' 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Bash-scripts 2 | ============ 3 | 4 | Miscellaneous scripts to enhance bash (prompt, adding directories to variables, ...) 5 | 6 | Table of Contents 7 | * [Scripts](#scripts) 8 | * [push.bashrc](#pushbashrc) 9 | * [ssh.bashrc](#sshbashrc) 10 | * [munge.bashrc](#mungebashrc) 11 | * [cyg-wrapper.sh](#cyg-wrappersh) 12 | * [Installation](#installation) 13 | 14 | ## Scripts 15 | 16 | ### push.bashrc 17 | 18 | This script provides a few helpers on top of pushd/popd/dirs functions. 19 | For a description of how these commands are used, see for instance 20 | 21 | 22 | This script overrides the default presentation of the three commands, and 23 | provides the following aliases: 24 | 25 | * `d`/`dirs` now displays one pushed directory per line, preceded by the 26 | directory index within the stack. (this is close to `\dirs -v`). 27 | When given an argument, `dirs` will display only the pushed directories that 28 | match the regex. 29 | 30 | * `p`/`pushd` and `popd` will display `dirs` result after each directories 31 | stack modification. 32 | 33 | * `p1` to `p9` are aliases on `pushd +1` to `pushd +9` 34 | 35 | * `g`/`go` searches for a pushed directory in the stack that matches all the 36 | regexes received as parameters. If several directories match, the list of 37 | matching directories is displayed, and the current directory is left 38 | unchanged. 39 | 40 | Other similar aliases can be found over internet, see for instance: 41 | . 42 | 43 | 44 | Other commands aimed at storing bash configuration (directories pushed and 45 | environment variables) are also provided: 46 | 47 | * `save_conf ` saves the current directories pushed, `env` contents 48 | and history in the files `$SHELL_CONF/.dirs`, 49 | `$SHELL_CONF/.env`, and `$SHELL_CONF/.hist`. 50 | 51 | * `load_conf ` restores the configuration saved with the previous 52 | command. Actually the environment is not restored. However, the differences 53 | between the current and the saved environment are displayed. 54 | Bash autocompletion is defined for `load_conf`. 55 | 56 | The default value for `$SHELL_CONF` is `$HOME/.config/bash` 57 | 58 | ### ssh.bashrc 59 | 60 | This script is meant to be sourced from the `~/.bashrc`. It will ask for the 61 | pass-phrase, once, and then it will remember it for later. 62 | 63 | ### munge.bashrc 64 | 65 | This script is meant to be sourced from the `~/.bashrc` to help help filling 66 | paths into variables like `$PATH`. The main objective is to avoid duplicates in 67 | the path variables. 68 | 69 | For instance, with 70 | ```bash 71 | munge PATH "$HOME/bin" 72 | munge MANPATH "$HOME/man" 73 | ``` 74 | you won't end up with `$HOME/bin` twice, or more, into your `$PATH`. 75 | 76 | `munge VARIABLE new-path` will add the new path **before** the other ones. 77 | 78 | `munge VARIABLE new-path after` will add the new path **after** the other ones. 79 | 80 | The script also defines 81 | * `change_or_munge VARIABLE old-path new-path` to replace a path 82 | * `remove_path VARIABLE paths-to-remove...` to remove a list of paths 83 | * `clean_path VARIABLE` to remove duplicates 84 | * `munge_std_variables new-path` to define in one go `$PATH`, `$LD_LIBRARY_PATH`, `$MANPATH`, `$INFOPATH`, `$PKG_CONFIG_PATH` depending in what is found in the new directory 85 | 86 | All four commands come with autocompletion for bash. 87 | 88 | Also, after a 89 | 90 | ```bash 91 | munge FOOPATH /some/path 92 | munge FOOPATH /other/path 93 | ``` 94 | 95 | A `FOOPATH` alias will be automatically defined, it'll print `$FOOPATH` value, 96 | with each path on a new line. This means that if you use `munge` on `PATH`, 97 | `LD_LIBRARY_PATH`, or `MANPATH`, etc, eponym aliases will be defined! 98 | 99 | ### nm_and_grep.sh 100 | 101 | This small script encapsulates `nm` and `grep`. Typical uses are: 102 | ```bash 103 | # Find all libraries having the searched symbol: 104 | find . \( -name '*.so' -o -name '*.a' \) -exec nm_n_grep.sh {} symbol \; -print 105 | 106 | # Find in which library used in an executable defines the searched symbol: 107 | ldd executable | sed 's#.*=>[ ]*##' | xargs -I {} ~1/nm_n_grep.sh -b {} symbol 108 | ``` 109 | 110 | 111 | ### cyg-wrapper.sh 112 | #####Running a native win32 application from cygwin/bash 113 | 114 | The cygwin *NIX emulation layer completly changes the way the paths are 115 | managed. All the cygwin hierarchy appears under the `/`: new root directory as 116 | on unices. Unfortunately, MsWindows native tools (i.e. not using the cygwin 117 | layer) can't understand paths expressed in the UNIX way. In order to convert 118 | *NIX (i.e. cygwin)-paths into plain MsWindows-paths, we can use: `cygpath -w`. 119 | 120 | But, Cygwin also permits many nice things like symbolic links -- try `man ln`. 121 | Unfortunately, *cygpath* seems (at this time) unable to follow these links and 122 | to return the exact MsWindows-path to the linked-files. 123 | 124 | Moreover, I had many headaches with the management of spaces on MsWindows 9x 125 | series when using command line invocation of native win32 tools. 126 | 127 | So here is `cyg-wrapper.sh`, a shell script that fixes all these problems. It 128 | permits to launch native win32 applications from command-line (or even from 129 | Mutt) with any kind of pathnames passed as parameters. 130 | 131 | 132 | #####Usage 133 | To get help on the way to use cyg-wrapper, try `cyg-wrapper.sh --help | less`. 134 | 135 | In my `~/.profile`, I usually have the following to run native win32 gvim from 136 | cygwin: 137 | 138 | ```bash 139 | ### Vim 140 | ## Little trick for LaTeX-Suite: 141 | # If one of the parameters is a (La)TeX file, then we declare the 142 | # servername to be �LATEX�. 143 | gvim() { 144 | opt='' 145 | if [ `expr "$*" : '.*tex\>'` -gt 0 ] ; then 146 | opt='--servername LATEX ' 147 | fi 148 | cyg-wrapper.sh "C:/Progra~1/Edition/vim/vim74/gvim.exe" --binary-opt=-c,--cmd,-T,-t,--servername,--remote-send,--remote-expr --cyg-verbose --fork=2 $opt "$@" 149 | } 150 | ### Some other windows programs 151 | alias explore='cyg-wrapper.sh "explorer" --slashed-opt' 152 | alias mplayer='cyg-wrapper.sh "c:/Progra~1/Window~1/mplayer2.exe"' 153 | ``` 154 | 155 | As a consequence, we can type this. 156 | 157 | ```bash 158 | gvim /etc/profile -c /PS1 -c "echo 'correctly opened'" 159 | # or even: 160 | cd ~/tmp ; ln -s ~/bin/cyg-wrapper.sh 161 | gvim -d http://hermitte.free.fr/cygwin/cyg-wrapper.sh cyg-wrapper.sh 162 | 163 | explorer -e 164 | explorer "$vim" 165 | explorer http://hermitte.free.fr/ 166 | ``` 167 | 168 | #####Requirements 169 | * *cyg*Utils to run and more precisely `realpath`. 170 | 171 | ## Installation 172 | 173 | In order to install all these scripts into `$HOME/bin`, just run 174 | ```bash 175 | ./install.sh 176 | ``` 177 | 178 | Or, if you'd rather install them elsewhere like `/share/stuff/bin`, type 179 | ```bash 180 | ./install.sh /share/stuff 181 | ``` 182 | 183 | -------------------------------------------------------------------------------- /cyg-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Note: for bash only! 3 | # ====================================================================== 4 | # AUTHOR: Luc Hermitte 5 | # 6 | # 7 | # 8 | # CREDITS: Jonathon M. Merz -> --fork option 9 | # Matt Armstrong -> --cyg-env-... options 10 | # John Aldridge -> For pointing me to "$COMSPEC /c start" 11 | # Matthias Morche -> fix for scp://, http://, ... paths 12 | # Zhiguo Yao -> Don't convert to DOS short form 13 | # Gilbert Goodwill -> Support of MSWindows' UNC pathes ; Support 14 | # for new behaviour of realpath 15 | # James Kanze -> Patch for --fork=2 16 | # 17 | # LAST UPDATE: 05th Mar 2016 18 | version="2.21" 19 | # 20 | # NOTES: {{{1 21 | # IMPORTANT: this shell script is for cygwin *ONLY*! 22 | # 23 | # This version requires cygUtils ; and more precisely: realpath (1). 24 | # 25 | # Some versions previous to important changes in the script are still 26 | # avaible, see the history. 27 | # 28 | # As bash will interpret backslashes before any program can see them, if you 29 | # want to pass pathnames containing backslashes, you will have to either 30 | # double the backslashes or to write them between a pair of (double or 31 | # single) quotes. 32 | # 33 | # PURPOSE: {{{1 34 | # This script wraps the calls to native win32 tools from cygwin. The 35 | # pathnames of the file-like arguments for the win32 tools are 36 | # translated in order to be understandable by the tools. 37 | # 38 | # It converts any pathname into its windows (long) form. 39 | # Symbolic links are also resolved, whatever their indirection level is. 40 | # 41 | # It accepts windows pathnames (relative or absolute) (backslashed or 42 | # forwardslashed), *nix pathnames (relative or absolute). 43 | # 44 | # USAGE: {{{1 45 | 46 | usageversion() { 47 | prog=`basename $0` 48 | usage="Usage: $prog PROGRAM [OPTIONS] [PROG-PARAMETERS...]" 49 | if [ $# = 0 ] ; then 50 | echo $usage >&2 51 | echo " $prog -h|--help">&2 52 | else 53 | cat <= 1 : Display the command really executed 96 | >= 2 : Display the values of the parameters given to cyg-wrapper 97 | --fork=<0, 1 or 2> 98 | 0: (default) Does not fork the new process. Can be used to override a 99 | previous --fork=1 argument. 100 | 1: Forks the new process so the shell is still accessible. 101 | 2: Forks the new process and makes it independent from the shell, so 102 | the shell is still accessible and can be dismissed. 103 | Note: this option wraps a call to "\$COMSPEC /c". 104 | 105 | Typical use: 106 | The easiest way to use this script is to define aliases or functions. 107 | ~/.profile is a fine place to do so. 108 | 109 | Examples: 110 | alias vi='cyg-wrapper.sh "C:/Progra~1/Edition/vim/vim70/gvim.exe" 111 | --binary-opt=-c,--cmd,-T,-t,--servername,--remote-send,--remote-expr' 112 | 113 | gvim() { 114 | opt='' 115 | if [ \`expr "\$*" : '.*tex\\>'\` -gt 0 ] ; then 116 | opt='--servername LATEX ' 117 | fi 118 | cyg-wrapper.sh "F:/Progra~1/Edition/vim/vim70/gvim.exe" 119 | --binary-opt=-c,--cmd,-T,-t,--servername,--remote-send,--remote-expr 120 | --cyg-verbose --fork=2 \$opt "\$@" 121 | } 122 | 123 | alias explorer='cyg-wrapper.sh "explorer" --slashed-opt' 124 | 125 | alias darcs='cyg-wrapper.sh path/to/darc --keywords=get,changes,pull 126 | --path-opt=--repo' 127 | END 128 | fi 129 | } 130 | 131 | if [ $# = 0 ] ; then 132 | usageversion 133 | exit 1 134 | elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then 135 | usageversion -h 136 | exit 0 137 | fi 138 | 139 | # HISTORY: {{{1 140 | # A slower and older version not requiring cyg-utils is available at: 141 | # http://hermitte.free.fr/cygwin/cyg-wrapper-1.1.sh 142 | # 143 | # v 2.02 144 | # (*) Uses cygUtils (actually realpath to determine where a file really is). 145 | # (*) New option: --fork (thanks to Jonathon M. Merz) 146 | # (*) New syntax for "binary options" 147 | # 148 | # v 2.03 -> 2.09 149 | # (*) Bug fixes 150 | # (*) Improvments regarding --fork 151 | # (*) New options: --cyg-env-... (thanks to Matt Armstrong) 152 | # (*) Don't try to convert scp://, http://, ftp://, ... 153 | # (thanks to Matthias Morche) 154 | # The version 2.09 which converts pathnames to their Windows short form is 155 | # still available at: 156 | # http://hermitte.free.fr/cygwin/cyg-wrapper-2.9.sh 157 | # 158 | # v 2.10 159 | # (*) Converts pathnames to their Windows short form 160 | # (*) Little speedup in the script ( ${var/pat/repl} is used instead of sed) 161 | # (*) The way pathnames made of spaces has been enhanced 162 | # (*) Don't convert to DOS short from anymore (thx to: Zhiguo Yao) 163 | # 164 | # v 2.11 -> 2.12 165 | # (*) Support of MSWindows' UNC pathes (thx to: Gilbert Goodwill) 166 | # 167 | # v 2.13 168 | # (*) First workaround to support parameters having spaces like in: 169 | # gvim -c "echo 'foo'" 170 | # However, ?gvim -c 'echo "foo"'? is not supported. 171 | # The version 2.13 which does not use Bash's arrays is still available at: 172 | # http://hermitte.free.fr/cygwin/cyg-wrapper-2.13.sh 173 | # 174 | # v 2.14 175 | # (*) Full support of parameters having spaces, thanks to Bash's arrays. 176 | # 177 | # v 2.15 178 | # (*) New option: --keywords 179 | # 180 | # v 2.16 181 | # (*) I've get rid of the external program ?expr?, and now I use bash's 182 | # internal funtionalities to parse the arguments. 183 | # => significant speed-up 184 | # (*) Convert parameters like: '--xxx={path}' -> new option: --path-opt 185 | # 186 | # v 2.17 187 | # (*) Optional number for cyg-verbose 188 | # 189 | # v 2.18 190 | # (*) The behaviour of realpath has changed. The script has been updated in 191 | # consequence. 192 | # 193 | # v.2.20 194 | # (*) Convert PROGRAM into Windows form 195 | # 196 | # }}}1 197 | # TODO: {{{1 198 | # (*) Convert parameters like: 'X{path}' 199 | # (*) --cyg-env-clear=HOMEPATH does not work while 200 | # --cyg-env-clear=PWD and --cyg-env-convert=HOMEPATH work... That's odd! 201 | # (*) Convert some special lists of directories like $MANPATH (but is it really 202 | # useful ?) 203 | # (*) Accept non DOS (short) form for PROGRAM 204 | # (*) $COMSPEC /c start gvim is not working anymore 205 | # (*) Enhance --keywords to support: 206 | # - the exact syntax of the program; e.g. the second ?cvf? in ?tar cvf cvf? 207 | # is a file, but not the first 208 | # - composed actions like with tar 209 | # 210 | # }}}1 211 | # ====================================================================== 212 | 213 | ## 0- Helper functions {{{1 214 | # @brief Function grealpath {{{2 215 | # @param $1 may be a local path, or any URL or . 216 | # @return What realpath should be returning: It is also resolves pathnames to 217 | # non yet existent files. 218 | # @author Gilbert Goodwill provided this function after realpath behaviour was 219 | # changed by its maintainers. 220 | function grealpath() 221 | { 222 | path=$1 223 | trim= 224 | 225 | # New realpath does not like non-existent paths 226 | val=`realpath "$path" 2>/dev/null` 227 | returned=$? 228 | # debug: echo returned=$returned 1>&2 229 | 230 | # While realpath is not succeeding, and not reached the top 231 | while ( [ $returned != 0 ] ) && ( [ $path != "/" ] ) && ( [ $path != ".." ] ) 232 | do 233 | # Try the parent directory by trimming after last / 234 | newtrim=`basename "$path"` 235 | path=`dirname "$path"` 236 | # debug: echo trim=$trim 1>&2 237 | # If something new was trimmed add on to total trimmed 238 | if [ "X$trim" != "X" ] 239 | then 240 | trim=$newtrim/$trim 241 | else 242 | trim=$newtrim 243 | fi 244 | # debug: echo $path / $trim 1>&2 245 | 246 | # Try realpath again 247 | rpout=`realpath "$path" 2>/dev/null` 248 | returned=$? 249 | # debug: echo returned=$returned 1>&2 250 | # debug: echo rpout=$rpout 1>&2 251 | 252 | # If realpath was successful on the path, add back in the trimmed 253 | if ( [ $returned == 0 ] &&[ "X$rpout" != "X/" ] ) 254 | then 255 | val=$rpout/$trim 256 | else 257 | val=/$trim 258 | fi 259 | done 260 | 261 | # Output the result of trimming the path with trimmed part tacked back on 262 | echo $val 263 | } 264 | 265 | # @brief Function transform_path {{{2 266 | # @param $1 may be a local path, or any URL or . 267 | # @return either the "win32" exact path for a possibly local file, or the 268 | # unmodified URL. A path is considered to be an URL when it matches 269 | # "[a-z]*://" 270 | # @todo Support and 271 | transform_path() { 272 | if [ "${1/[[:lower:]]*:\/\//}" != "$1" ] ; then 273 | # Some netrw protocol like or : leave 274 | # unchanged 275 | echo "$1" 276 | else 277 | # Convert pathname "$1" to absolute path (*nix form) and resolve 278 | # all the symbolic links 279 | ptransl=`grealpath "$1"` 280 | ptransl=`cygpath -wl "$ptransl"` 281 | echo "$ptransl" 282 | fi 283 | } 284 | 285 | 286 | # ====================================================================== 287 | # I- Initializations: {{{1 288 | # I.a- Default value for the various options {{{2 289 | # 290 | # Store the program name. 291 | declare -a param=($(cygpath -ms "$1")) 292 | shift; 293 | 294 | # Special arguments: 295 | # --slashed-opt : says that the program expects parameters of the form '/opt' 296 | # --binary-opt={opts} : lists of binary options whose 2nd element is not a file 297 | # --keywords={acts} : lists of actions like in ?apt-get update? 298 | # --path-opt={opts} : list of options taking a path after an equal sign 299 | # --cyg-verbose : forces echo of the command really executed 300 | # --fork=<[0]|1|2> : explicitly forks the process 301 | # --cyg-clear-env={vars} : lists of environment variables to unset 302 | # --cyg-convert-env={vars} : lists of environment variables whose pathnames must 303 | # be converted 304 | slashed_opt=0 305 | binary_args="" 306 | keywords="" 307 | path_options="" 308 | cyg_verb=0 309 | fork_option=0 310 | 311 | # I.b- checks cyg-wrapper.sh's arguments {{{2 312 | # Impl. note: ${1#*=} strips from $1 every character up to the equal sign. 313 | while [ $# -gt 0 ] ; do 314 | case "$1" in 315 | --slashed-opt ) slashed_opt=1;; 316 | --cyg-verbose=[0-9] ) cyg_verb=${1#*=};; 317 | --cyg-verbose ) cyg_verb=1;; 318 | --binary-opt=* ) binary_args=${1#*=};; 319 | --path-opt=* ) path_options=${1#*=};; 320 | --keywords=* ) keywords=${1#*=};; 321 | --fork=[012] ) fork_option=${1#*=};; 322 | --cyg-env-clear=* ) 323 | list=${1#*=} 324 | for i in ${list//,/ } ; do 325 | # This change is local to sub-processes only 326 | unset $i 327 | done 328 | ;; 329 | --cyg-env-convert=* ) 330 | list=${1#*=} 331 | for i in ${list//,/ } ; do 332 | # Need to have access to ${$i} -> "eval ... '$'$i" 333 | eval val='$'$i 334 | # The environment variable may not exist (/be exported) 335 | if [ ! "$val" = "" ] ; then 336 | val=`grealpath "$val"` 337 | val=`cygpath -wl "$val"` 338 | # This change is local to sub-processes only 339 | declare $i="$val" 340 | fi 341 | # echo val[$i]=$val 342 | done 343 | ;; 344 | *) break;; # no shift! 345 | esac 346 | shift 347 | done 348 | 349 | 350 | if [ $cyg_verb -gt 1 ] ; then 351 | echo "cyg_verb =$cyg_verb" 352 | echo "binary_args =$binary_args" 353 | echo "path_options =$path_options" 354 | echo "keywords =$keywords" 355 | echo "slashed_opt =$slashed_opt" 356 | echo "fork_option =$fork_option" 357 | fi 358 | 359 | # }}}1 360 | # ====================================================================== 361 | # II- Main loop {{{1 362 | 363 | # Loop that transforms PROGRAM's arguments {{{2 364 | # For each argument ... 365 | while [ $# -gt 0 ] ; do 366 | if [ "${binary_args/$1/}" != "$binary_args" ] ; then 367 | # Binary arguments: the next argument is to be ignored (not a file). 368 | # echo "<$1> found into <$binary_args>" 369 | param[${#param[*]}]="$1" 370 | shift 371 | param[${#param[*]}]="$1" 372 | elif [ "${keywords/$1/}" != "$keywords" ] ; then 373 | # Actions: the argument is to be ignored (not a file). 374 | # Todo: check to position of the keywords 375 | param[${#param[*]}]="$1" 376 | elif [ "${path_options/${1%=*}/}" != "$path_options" ] ; then 377 | # Special option of the form: "{option}={path}" 378 | # echo -n "Found path opt" 379 | # echo " ($1 ; ${1%=*}) = <${path_options/${1%=*}/}> VS $path_options" 380 | # 381 | # Extract and tranform the path written after the equal sign. 382 | p=`transform_path "${1#*=}"` 383 | # Push the complete option with the "win32"/URL path ito the list of 384 | # parameter. 385 | param[${#param[*]}]="${1%=*}=$p" 386 | else 387 | # Plain path or options. 388 | # echo "path opt ($1 ; ${1%=*}) = <${path_options/${1%=*}/}> VS $path_options" 389 | case "$1" in 390 | [-+]* ) # Option 391 | if [ $slashed_opt = 1 ] ; then 392 | param[${#param[*]}]="${1/-//}" 393 | else 394 | param[${#param[*]}]="$1" 395 | fi 396 | ;; 397 | 398 | * ) # Plain path 399 | # NB: must be done in two steps in order to not break arguments 400 | # having spaces. 401 | p=`transform_path "$1"` 402 | param[${#param[*]}]="$p" 403 | ;; 404 | esac 405 | fi 406 | 407 | # Next! 408 | shift 409 | done 410 | 411 | # }}}1 412 | # ====================================================================== 413 | # III- Execute the proper tool with the proper arguments. {{{1 414 | # verbose 415 | if [ $cyg_verb -gt 0 ] ; then 416 | # echo "$param" | sed s'#\\\\#\\#g' 417 | # echo ${param//\\\\\\\\/\\} 418 | echo "${param[@]}" 419 | fi 420 | # call PROGRAM 421 | # exit 422 | if [ $fork_option = 1 ] ; then 423 | # `echo "$param" | xargs -t $xargs_param` & 424 | # WAS (2.13): eval $param & 425 | # eval "${param[@]}" & 426 | "${param[@]}" & 427 | elif [ $fork_option = 2 ] ; then 428 | # That's very odd. This does not work anymore... 429 | # I do know if it comes from XP's last update or cygwin last update 430 | comspec=$(cygpath -u $COMSPEC) 431 | # WAS (2.13): eval $comspec /c start $param 432 | # eval $comspec /c start "${param[@]}" 433 | 434 | # (2.18) 435 | $comspec /c start "${param[@]}" 436 | 437 | # this seems to work, at least in my configuration (JAK, 28/4/2010) 438 | # $comspec /c "${param[@]}" 439 | 440 | # Other solutions rejected. 441 | # Be aware that cygstart accepts a very limited number of characters as 442 | # parameters, and that cygstart will steal ALL the parameters given to 443 | # PROGRAM, unless ?--? is used. 444 | # However, this solution is still working while $COMSPEC's one is not 445 | # cygstart -- "${param[@]}" 446 | # cygstart "${param[@]}" 447 | # 448 | # Other solution which seems to not work 449 | # "${param[@]}" <&0 & 450 | # disown 451 | else 452 | # `echo "$param" | xargs $xargs_param` 453 | # WAS (2.13): eval $param 454 | # eval "${param[@]}" 455 | "${param[@]}" 456 | fi 457 | # }}}1 458 | # ====================================================================== 459 | # vim600: set fdm=marker tw=79: 460 | -------------------------------------------------------------------------------- /forward_completion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Inspired by http://stackoverflow.com/questions/3520936/accessing-bash-completions-for-specific-commands-programmatically 3 | # Licence: CC-BY-NC-SA 4 | 5 | ## Helper functions {{{1 6 | # __print_completions() {{{2 7 | __print_completions() { 8 | printf '%s\n' "${COMPREPLY[@]}" | sort 9 | } 10 | 11 | # _die {{{2 12 | function _die() 13 | { 14 | local msg=$1 15 | [ -z "${msg}" ] && msg="Died" 16 | # printf "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: ${FUNCNAME[1]}: ${msg}" >&2 17 | printf "${msg}" >&2 18 | exit 0 19 | } 20 | 21 | command=$1 22 | 23 | ## Main code {{{1 24 | # load bash-completion functions 25 | source /etc/bash_completion 26 | 27 | # load command completion function 28 | _completion_loader ${command} 29 | compl_def=$(complete -p ${command}) 30 | policy="${compl_def/complete -F /}" 31 | [ "${policy}" != "$compl_def" ] || _die "Forwarding completion for this type of command isn't supported yet" 32 | pol_tokens=(${policy}) 33 | [ ${pol_tokens[1]} == "${command}" ] || _die "Unexpected situation" 34 | 35 | COMP_LINE="$@" 36 | COMP_WORDS=("$@") 37 | COMP_POINT=${#COMP_LINE} 38 | ((++COMP_POINT)) 39 | COMP_CWORD=1 40 | ${pol_tokens[0]} 41 | __print_completions 42 | 43 | # }}}1 44 | # vim:ft=sh:fdm=marker 45 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script Purpose {{{1 4 | # This scripts helps to install Bash-Scripts into $HOME/bin. 5 | # Hard links will be created in ~/bin for the main scripts in the 6 | # current directory. 7 | # 8 | 9 | 10 | # License: CC-BY-SA 3.0 v2 {{{1 11 | 12 | # Code {{{1 13 | 14 | # Obtain current script dir {{{2 15 | # http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in/2633580#2633580 16 | # This comment and code Copyleft, selectable license under the GPL2.0 or 17 | # later or CC-SA 3.0 (CreativeCommons Share Alike) or later. (c) 2008. 18 | # All rights reserved. No warranty of any kind. You have been warned. 19 | # http://www.gnu.org/licenses/gpl-2.0.txt 20 | # http://creativecommons.org/licenses/by-sa/3.0/ 21 | current_dir() { 22 | pushd $(dirname $(readlink -f "$BASH_SOURCE")) > /dev/null 23 | local SCRIPT_DIR="$PWD" 24 | popd > /dev/null 25 | echo $SCRIPT_DIR 26 | } 27 | # ---- 28 | 29 | # Usage and options {{{2 30 | usage() { 31 | echo "USAGE: $0 [-v|--verbose] [HOMEDIR]" 32 | echo "USAGE: $0 [-h|--help]" 33 | } 34 | 35 | 36 | verbose=0 37 | HOMEDIR="" 38 | 39 | while [ $# -gt 0 ] ; do 40 | case $1 in 41 | -h|--help) 42 | usage 43 | exit -1 44 | ;; 45 | -v|--verbose) 46 | verbose=1 47 | shift 48 | ;; 49 | *) 50 | if [ x"$HOMEDIR0" != x"" ] ; then 51 | echo "$0: Error HOMEDIR already overridden" 52 | usage 53 | exit 1 54 | fi 55 | HOMEDIR0=$1 56 | shift 57 | ;; 58 | esac 59 | done 60 | HOMEDIR=${HOMEDIR0:-$HOME} 61 | 62 | # The main code 63 | 64 | ORIG=$(current_dir) 65 | cd "$ORIG" 66 | 67 | files=$(ls *.bashrc *.sh) 68 | cd "$HOMEDIR/bin" 69 | if [ $verbose -gt 0 ] ; then 70 | echo cd "$HOMEDIR/bin" 71 | fi 72 | for f in $files ; do 73 | case $f in 74 | install.sh) # ignore this script 75 | continue 76 | ;; 77 | cyg-wrapper.sh) # ignore cyg-wrapper.sh on non-cygwin systems 78 | uname=$(uname) 79 | if [ "${uname/CYGWIN/}" = "$uname" ] ; then 80 | continue 81 | fi 82 | ;; 83 | esac 84 | 85 | if [ $verbose -gt 0 ] ; then 86 | echo ln "$ORIG/$f" 87 | fi 88 | rm "$f" 89 | ln "$ORIG/$f" 90 | done 91 | 92 | 93 | # vim:set fdm=marker: 94 | 95 | -------------------------------------------------------------------------------- /list_threads.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # A (b)ash script replacement for ps showing threads and other helpful stuff. 4 | # Especially useful for Busybox based systems which has a very simple ps applet 5 | # 6 | # License: GPLv2 7 | # Copyright 2009 Chris Simmonds, 2net Ltd 8 | # chris@2net.co.uk 9 | 10 | # See http://2net.co.uk/tutorial/list_threads 11 | 12 | show_details () 13 | { 14 | # Read the stat entry for this process/thread. See man 5 proc for description 15 | read _PID _COMM _STATE _PPID _PGRP _SESSION _TTY_NR _TPGID _FLAGS _MINFLT _CMINFLT _MAJFLT \ 16 | _CMAJFLT _UTIME _STIME _CUTIME _CSTIME _PRIORITY _NICE _NUM_THREADS _IRETVALUE \ 17 | _STARTTIME _VSIZE _RSS _RSSLIM _STARTCODE _ENDCODE _STARTSTACK _KSTKESP _KSTKEIP \ 18 | _SIGNAL _BLOCKED _SIGIGNORE _SIGCATCH _WCHAN _NSWAP _CNSWAP _EXIT_SIGNAL _PROCESSOR \ 19 | _RT_PRIORITY _POLICY _JUNK < /proc/$PID_TO_SHOW/stat 20 | 21 | # Decode policy and priority 22 | case $_POLICY in 23 | "0") 24 | POLICY="TS" 25 | RTPRIO="- " 26 | ;; 27 | "1") 28 | POLICY="FF" 29 | RTPRIO=$_RT_PRIORITY 30 | ;; 31 | "2") 32 | POLICY="RR" 33 | RTPRIO=$_RT_PRIORITY 34 | ;; 35 | *) 36 | POLICY="??" 37 | RTPRIO="- " 38 | esac 39 | # _WCHAN is the address of the kernel function the task is blocked 40 | # in: not much use, so read /proc/NN/wchan to get the name of the function 41 | read _WCHAN < /proc/$PID_TO_SHOW/wchan 42 | 43 | # The output is more or less equivalent to "ps -Leo pid,tid,class,rtprio,stat,comm,wchan" 44 | echo -e "$PID\t$TID\t$POLICY\t$RTPRIO\t$_STATE\t$_COMM\t$_WCHAN" 45 | 46 | # Of course, you can easily change the line above to output more or less information 47 | # Here is an example which adds nice, vsize and rss 48 | # echo -e "$PID\t$TID\t$POLICY\t$RTPRIO\t$_NICE\t$_STATE\t$_VSIZE\t$_RSS\t$_COMM\t$_WCHAN" 49 | 50 | } 51 | 52 | # Print banner. If you change show_details() to output more (or different) 53 | # information, change this as well so you know what is what 54 | echo -e "PID\tTID\tCLS\tRTPRIO\tSTAT\tCOMMAND\tWCHAN" 55 | # echo -e "PID\tTID\tCLS\tRTPRIO\tNICE\tSTAT\tVSIZE\tRSS\tCOMMAND\tWCHAN" 56 | 57 | # Get a list of processes from /proc 58 | 59 | # Doing it like this gives a numerical listing. The simpler "for p in /proc/[0-9]*" 60 | # would give an alphabetic list in which 2 comes after 10 rather than before. 61 | # N.B. Assumes PIDs are 5 digits or fewer (check /proc/sys/kernel/pid_max) 62 | for p in /proc/[0-9] /proc/[0-9][0-9] /proc/[0-9][0-9][0-9] /proc/[0-9][0-9][0-9][0-9] /proc/[0-9][0-9][0-9][0-9][0-9]; do 63 | PID=$(basename $p) 64 | if [ -f /proc/$PID/stat ]; then 65 | TID=$PID 66 | PID_TO_SHOW=$PID 67 | show_details 68 | 69 | # Look in /proc/NNNN/task for a list of threads 70 | for t in $p/task/*; do 71 | TID=$(basename $t) 72 | if [ $TID != $PID ]; then 73 | PID_TO_SHOW=$TID 74 | show_details 75 | fi 76 | done 77 | fi 78 | done 79 | -------------------------------------------------------------------------------- /munge.bashrc: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | ## Paths list concatenations that avoid duplicates 3 | # Script initially found in the /etc of a linux distribution, then 4 | # patched by Luc Hermitte. 5 | # Licence, likely GPL v2. To be confirmed. 6 | # 7 | # Examples: 8 | # $ munge PATH "$HOME/bin" 9 | # $ munge MANPATH "$HOME/man" 10 | unset verbose_munge 11 | # verbose_munge=1 12 | 13 | ## Helper functions {{{1 14 | # _is_unset {{{2 15 | function _is_unset() 16 | { 17 | [[ -z ${!1+x} ]] 18 | } 19 | 20 | # _is_set {{{2 21 | function _is_set() 22 | { 23 | # [[ -v $1 ]] with bash 4.2+ 24 | [[ -n ${!1+x} ]] 25 | } 26 | 27 | # _die {{{2 28 | function _die() 29 | { 30 | local msg=$1 31 | [ -z "${msg}" ] && msg="Died" 32 | # printf "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: ${FUNCNAME[1]}: ${msg}" >&2 33 | printf "${msg}" >&2 34 | return 0 35 | } 36 | 37 | # _split_path {{{2 38 | function _split_path() 39 | { 40 | local IFS=: 41 | local res=( $1 ) 42 | echo "${res[@]}" 43 | } 44 | 45 | # _filter_array {{{2 46 | # remove all occurrences of pattern from array elements 47 | # $1: pattern 48 | # $2+: array to filter 49 | function _filter_array() 50 | { 51 | declare -a res 52 | local pat=$1 53 | shift 54 | for e in "$@"; do 55 | [[ "${e}" != "${pat}" ]] && res+=("$e") 56 | done 57 | echo "${res[@]}" 58 | } 59 | 60 | ## Path list manipulation functions {{{1 61 | # munge {{{2 62 | function munge() 63 | { 64 | if [ $# -lt 2 ] ; then 65 | echo "munge [after]" 66 | echo "" 67 | echo "See also: change_or_munge, and remove_path" 68 | return 1 69 | fi 70 | local var=$1 71 | # local val=$(eval echo \$$1) 72 | local val=${!1} 73 | 74 | _is_unset "${var}" && [[ "${verbose_munge}" = "1" ]] && _die "munge [after]\n \$$1 does not exist." && return 1 75 | 76 | # linux -> egrep -q, 77 | # solaris -> egrep 78 | if [ -d "$2" ] ; then 79 | if ! echo $val | /bin/egrep -q "(^|:)$2($|:)" ; then 80 | if [ "$3" = "after" ] ; then 81 | eval $var=$(echo -ne \""$val:$2"\") 82 | else 83 | # echo $var=$2:$val 84 | eval $var=$(echo -ne \""$2:$val"\") 85 | # echo $var=$(eval echo \$$var) 86 | fi 87 | # else 88 | elif [ "${verbose_munge+set}" = "set" ] ; then 89 | echo "path already in $var ($2)" 90 | fi 91 | else 92 | if [[ "${verbose_munge+set}" = "set" ]] ; then 93 | echo "inexistent path not added to $var ($2)" 94 | fi 95 | return 2 96 | fi 97 | # Add an alias over variable name to simplify its display 98 | alias $var="echo \$$var | tr ':' '\n'" 99 | return 0 100 | } 101 | 102 | # change_or_munge {{{2 103 | # replaces $2 by $3 in $1 unless it is not present. In that case, $3 is 104 | # munged into $1 105 | function change_or_munge() 106 | { 107 | if [ $# -lt 2 ] ; then 108 | echo "change_or_munge " 109 | echo "" 110 | echo "See also: munge, and remove_path" 111 | return 1 112 | fi 113 | local var=$1 114 | # local val=$(eval echo \$$1) 115 | local val=${!1} 116 | _is_unset "${var}" && _die "change_or_munge \n \$$1 does not exist." && return 1 117 | local old=$2 118 | local new=$3 119 | # linux -> egrep -q, 120 | # solaris -> egrep 121 | if ! echo $val | /bin/egrep -q "(^|:)$2($|:)" ; then 122 | munge "$1" "$3" "$4" 123 | else 124 | # echo "replace $old with $new" 125 | val=$(echo $val | perl -pe "s#(^|:)$old(\$|:)#\\1$new\\2#") 126 | eval $var=$(echo -ne \""$val"\") 127 | fi 128 | echo $val | tr ':' '\n' 129 | return 0 130 | } 131 | 132 | # remove path {{{2 133 | function remove_path() 134 | { 135 | if [ $# -lt 2 ] ; then 136 | echo "remove_path ..." 137 | echo "" 138 | echo "See also: munge, and change_or_munge" 139 | return 1 140 | fi 141 | local var=$1 142 | # local val=$(eval echo \$$1) 143 | local val=${!1} 144 | _is_unset "${var}" && _die "remove_path ...\n \$$1 does not exist." && return 1 145 | shift 146 | while [ $# -ge 1 ] ; do 147 | local old=$1 148 | val=$(echo $val | perl -pe "s#(^|:)$old(\$|:)#\\1#;s#::#:#;s#^:|:\$##") 149 | eval $var=$(echo -ne \""$val"\") 150 | val=$(eval echo \$$var) 151 | shift 152 | done 153 | echo $val | tr ':' '\n' 154 | return 0 155 | } 156 | 157 | # lh_test() { 158 | # echo "VAR=$1 VALUE=$(eval echo \$$1)" 159 | # } 160 | 161 | # =========================================================================== 162 | # Paths cleaning {{{2 163 | # apply a kind a O(n^2) uniq that clean duplicates 164 | function clean_path() 165 | { 166 | var=$1 167 | val=$(eval printf \$$1) 168 | declare -a dirs 169 | # dirs=(${val//:/ }) 170 | # split at each element, supports pathnames containing whitepaces 171 | OLD=$IFS 172 | local IFS=':' 173 | dirs=(${val}) 174 | local IFS=$OLD 175 | 176 | declare -a res 177 | declare -a end=(${dirs[@]}) 178 | while [ ${#end[@]} -gt 0 ] 179 | do 180 | crt=${end[0]} # head 181 | end=("${end[@]:1}") # tail 182 | # remove all occurrences of $crt in the tail ($end) 183 | duplicate=0 184 | i=0 185 | while [ $i -ne ${#end[@]} ] ; do 186 | if [ "${end[$i]}" = "$crt" ] ; then 187 | unset end[$i] 188 | duplicate=1 189 | else 190 | i=$(($i+1)) 191 | fi 192 | done 193 | if [ $duplicate -eq 0 ] ; then 194 | # echo "$crt" 195 | res=( "${res[@]}" "${crt}") 196 | fi 197 | done 198 | 199 | local IFS=':' 200 | str="${res[*]}" 201 | local IFS=$OLD 202 | # echo $str 203 | eval $var=$(echo -ne \""$str"\") 204 | return 0 205 | } 206 | 207 | # munge_std_variables {{{2 208 | # Given the path received, tries to fill PATH, MANPATH, LD_LIBRARY_PATH, 209 | # PKG_CONFIG_PATH... 210 | function munge_std_variables() 211 | { 212 | if [ $# -lt 1 ] ; then 213 | echo "munge_std_variables [after]" 214 | return 1 215 | fi 216 | local path=$1 217 | 218 | if [ ! -d "${path}" ] ; then 219 | if [[ "${verbose_munge+set}" = "set" ]] ; then 220 | echo "inexistent path not added to std variables (${PATH})" 221 | fi 222 | return 1 223 | fi 224 | munge PATH "${path}/bin" $2 225 | munge LD_LIBRARY_PATH "${path}/lib" $2 226 | munge LD_LIBRARY_PATH "${path}/lib64" $2 227 | munge MANPATH "${path}/man" $2 228 | munge MANPATH "${path}/share/man" $2 229 | munge INFOPATH "${path}/info" $2 230 | munge INFOPATH "${path}/share/info" $2 231 | munge PKG_CONFIG_PATH "${path}/lib/pkgconfig" $2 232 | return 0 233 | } 234 | 235 | ## Completion {{{1 236 | # munge {{{2 237 | function _munge() 238 | { 239 | local cur=${COMP_WORDS[COMP_CWORD]} 240 | case $COMP_CWORD in 241 | 1) COMPREPLY=( $(compgen -v ${cur}) ) 242 | # Add a space in variable names case 243 | ;; 244 | *) COMPREPLY=( $(compgen -d ${cur}) ) 245 | # Add a trailling '/' to the result found 246 | if [[ ${#COMPREPLY[@]} -eq 1 ]]; then 247 | i=${COMPREPLY[0]} 248 | if [[ "$i" == "$cur" && $i != "*/" ]]; then 249 | COMPREPLY[0]="${i}/" 250 | fi 251 | fi 252 | 253 | # Don't add a space in directories case 254 | compopt -o nospace 255 | ;; 256 | esac 257 | } 258 | complete -F _munge munge 259 | 260 | # remove_path {{{2 261 | function _remove_path() 262 | { 263 | export cas=0 264 | local cur=${COMP_WORDS[COMP_CWORD]} 265 | case $COMP_CWORD in 266 | 1) COMPREPLY=( $(compgen -v ${cur}) ) ;; 267 | *) 268 | declare -a used=( "${COMP_WORDS[@]:2}" ) 269 | unset used[${#used[@]}-1] 270 | ;& # fallthrough 271 | 2) 272 | local envname=${COMP_WORDS[1]} 273 | local paths=( $(_split_path ${!envname}) ) 274 | COMPREPLY=( $(compgen -W "$(printf "%s\n" "${paths[@]}")" -- ${cur}) ) 275 | if [ -n "${used}" ] ; then 276 | cas+=* 277 | for p in "${used[@]}" ; do 278 | COMPREPLY=( $(_filter_array "${p}" "${COMPREPLY[@]}")) 279 | done 280 | fi 281 | ;; 282 | esac 283 | } 284 | complete -F _remove_path remove_path 285 | 286 | # change_or_munge {{{2 287 | function _change_or_munge() 288 | { 289 | local cur=${COMP_WORDS[COMP_CWORD]} 290 | case $COMP_CWORD in 291 | 1) COMPREPLY=( $(compgen -v ${cur}) ) ;; 292 | 2) local envname=${COMP_WORDS[1]} 293 | local paths=( $(_split_path ${!envname}) ) 294 | COMPREPLY=( $(compgen -W "$(printf "%s\n" "${paths[@]}")" -- ${cur}) ) ;; 295 | *) COMPREPLY=( $(compgen -d ${cur}) ) ;; 296 | esac 297 | } 298 | complete -F _change_or_munge change_or_munge 299 | 300 | # clean_path {{{2 301 | complete -v clean_path 302 | 303 | # munge_std_variables {{{2 304 | complete -d munge_std_variables 305 | 306 | # }}}1 307 | # vim:ft=sh:fdm=marker 308 | -------------------------------------------------------------------------------- /nm_n_grep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright Luc Hermitte 2006-2025, all rigths reserved 3 | # Licence GPL v3 4 | 5 | usage() { 6 | echo "nm_n_grep.sh [--brief|-b] " 7 | echo " Typical use:" 8 | echo " find . \( -name '*.so' -o -name '*.a' \) -exec nm_n_grep.sh {} symbol \; -print" 9 | echo " ldd executable | sed 's#.*=>[ ]*\\([^ ]*\\).*#\\1#' | xargs -I {} nm_n_grep.sh -b {} symbol" 10 | } 11 | 12 | case $1 in 13 | -h|--help) usage ; exit 0 ;; 14 | esac 15 | if [ $# -lt 2 ] ; then echo "$0: Syntax error" ; usage ; exit 1 ; fi 16 | 17 | brief=0 18 | file='' 19 | regex='' 20 | 21 | while [ $# -gt 0 ] ; do 22 | case $1 in 23 | -b|--brief) 24 | brief=1 25 | ;; 26 | *) 27 | if [ x"$file" == x"" ] ; then 28 | file=$1 29 | else 30 | regex=$1 31 | fi 32 | ;; 33 | esac 34 | shift 35 | done 36 | 37 | if [ $brief -eq 1 ] ; then 38 | (nm -CU $file 2>/dev/null | grep $regex > /dev/null) && echo "$regex found in $file" 39 | else 40 | nm -CU $file 2>/dev/null | grep $regex 41 | fi 42 | -------------------------------------------------------------------------------- /push.bashrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LucHermitte/Bash-scripts/HEAD/push.bashrc -------------------------------------------------------------------------------- /ssh.bashrc: -------------------------------------------------------------------------------- 1 | # See also: https://github.com/wwalker/ssh-find-agent 2 | # 3 | ## SSH 4 | SSH_ENV=${SSH_ENV:-"$HOME/.ssh/environment"} 5 | SSH_KEYS="${SSH_KEYS:-}" 6 | 7 | ## Stop on logout 8 | # See http://jowisoftware.de/wp/2012/04/managing-ssh-agent-automatically-with-cygwinputty-support/ 9 | if [[ "$OSTYPE" = cygwin ]] ; then 10 | __instances_tgt=1 11 | _count_instances () { 12 | ps | grep -wc [m]intty 13 | } 14 | else 15 | __instances_tgt=2 16 | function _count_instances() { 17 | # ps aux | grep -wc [b]ash 18 | # The fact this is called in a function adds one to number bash 19 | # processes detected -> __instances_tgt=2 20 | pgrep -u $USER bash | wc -l 21 | } 22 | fi 23 | 24 | _on_exit_stop_agent() { 25 | local nb_instances=$(_count_instances) 26 | if [ ${nb_instances} -eq ${__instances_tgt} ] ; then 27 | echo "Terminating ssh-agent" 28 | ssh-add -D >/dev/null 2>&1 29 | ssh-agent -k >/dev/null 2>&1 30 | else 31 | echo "$((${nb_instances}-1)) terminals still running. ssh-agent is kept." 32 | fi 33 | } 34 | trap '_on_exit_stop_agent' EXIT 35 | 36 | # start the ssh-agent 37 | function start_agent { 38 | echo "Initializing new SSH agent..." 39 | # spawn ssh-agent 40 | test -f "${SSH_ENV}" && rm "${SSH_ENV}" 41 | ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}" 42 | echo succeeded 43 | chmod 600 "${SSH_ENV}" 44 | . "${SSH_ENV}" > /dev/null 45 | ssh-add ${SSH_KEYS} 46 | } 47 | 48 | # test for identities 49 | function test_identities { 50 | # test whether standard identities have been added to the agent already 51 | ssh-add -l | grep "The agent has no identities" > /dev/null 52 | if [ $? -eq 0 ]; then 53 | ssh-add ${SSH_KEYS} 54 | # $SSH_AUTH_SOCK broken so we start a new proper agent 55 | if [ $? -eq 2 ];then 56 | start_agent 57 | fi 58 | fi 59 | } 60 | 61 | if [ ${SSH_AGENT_IS_HIDDEN:-0} -eq 1 ] ; then 62 | # Sometimes, I'm on a machine that hides ssh-agent process. 63 | # Let's instead suppose that if ssh-add -l returns a valid number 64 | # which means there is an agent running around 65 | function _ssh_test_agent { 66 | ssh-add -l > /dev/null 2>&1 67 | } 68 | else 69 | function _ssh_test_agent { 70 | ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null 71 | } 72 | fi 73 | 74 | function _ssh_run_env { 75 | # if $SSH_AGENT_PID is not properly set, we might be able to load one from 76 | # $SSH_ENV 77 | . "${SSH_ENV}" > /dev/null 78 | _ssh_test_agent && test_identities || start_agent 79 | } 80 | 81 | # check for running ssh-agent with proper $SSH_AGENT_PID 82 | [ -n "$SSH_AGENT_PID" ] && _ssh_test_agent \ 83 | && test_identities \ 84 | || _ssh_run_env 85 | 86 | return 87 | 88 | # This (old) version generates the following error message: 89 | # Usage : grep [OPTION]... PATTERN [FILE]... 90 | ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null 91 | if [ $? -eq 0 ]; then 92 | test_identities 93 | # if $SSH_AGENT_PID is not properly set, we might be able to load one from 94 | # $SSH_ENV 95 | else 96 | . "${SSH_ENV}" > /dev/null 97 | ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null 98 | if [ $? -eq 0 ]; then 99 | test_identities 100 | else 101 | start_agent 102 | fi 103 | fi 104 | --------------------------------------------------------------------------------