nish-functions-0.5/000075500000000000000000000000001112243173600143235ustar00rootroot00000000000000nish-functions-0.5/Makefile000064400000000000000000000011461112243173600157650ustar00rootroot00000000000000DESTDIR= PREFIX=$(DESTDIR)/usr LIBEXEC=libexec LIBEXECDIR=$(PREFIX)/$(LIBEXEC)/nish BINDIR=$(PREFIX)/bin LIBS=functions JUNK= o oo ooo o.* *~ GENERATED=functions.locate.new all: functions.locate.new README.new clean: rm -rf $(JUNK) $(GENERATED) README.new: README sed 's@LIBEXEC@$(LIBEXECDIR)@g' $< > $@ functions.locate.new: functions.locate sed 's@^__LIBEXEC=.*@__LIBEXEC="\$(LIBEXECDIR)"@g' $< > $@ install: all mkdir -p "$(LIBEXECDIR)" "$(BINDIR)" install -m755 functions.locate.new "$(BINDIR)"/functions.locate install -m755 $(LIBS) "$(LIBEXECDIR)" suck: cd ~ && git pull cp ~/bin/functions* ./ nish-functions-0.5/README000064400000000000000000000000671112243173600152060ustar00rootroot00000000000000Run LIBEXEC/function to get detailed help on functions nish-functions-0.5/README.new000064400000000000000000000001011112243173600157630ustar00rootroot00000000000000Run /usr/libexec/nish/function to get detailed help on functions nish-functions-0.5/functions000075500000000000000000000276261112243173600162760ustar00rootroot00000000000000#!/bin/sh ################################################ # # This is supplementary functions file # it is not intended to be called directly # see functions digest below # # Any global variable or function name defined here MUST start with "_" # to avoid namespace clash (all user-defined names must NOT start with "_") # Names started with two _'s are internals and should not be used outside ################################################ # Variables: export _Me=`basename "$0"` # script name test -n "$_GMe" || export _GMe="$_Me" # global script name (for set of scripts) export _FMe=`realpath "$0"` # script fullpath export _MeDir=`dirname "$_FMe"` # script directory export _MePID="$$" # PID of current shell test -n "$_Home" || export _Home="$HOME" # base directory export _AMe=`echo "$_Me" | tr -cd "[:alnum:]"` # script name alphanumeric part (for generating filenames) export _RC="$_Home/.$_GMe"rc # config file export _RC_HOST="$_Home/.$_GMe"rc."`hostname`" # host specific config file export _Verb=0 # verbosity level export _Options="" # getopts options (generated!) export _Usage="" # short help string export _Help="" # long help string export _TmpFiles="" # temporary files export _TmpDirs="" # temporary directories export _LC_COLLATE=C # LC_COLLATE submissions export __Version=0.5 # this functions file version export _Version=0.0 # software version __CR=" " __Unsafe="" # set this to non-empty to enable unsafe actions #(like non-/tmp/-directory deleting etc.) # LC_COLLATE wrappers (e. g. for [a-z] regexps work properly etc.) # sed grep sed() { env LC_COLLATE="$_LC_COLLATE" sed "$@"; } grep() { env LC_COLLATE="$_LC_COLLATE" grep "$@"; } ################################################ # Message displaying and error system # Internal: display a message # Onw may redefine this (e.g. with XDialog) for another displaying method __Message() { # message [title] { test -n "$2" && echo "$2: $1" || echo "$1"; } >&2 } # Display an error to stderr # check _Verb if to display message # exit if errorlevel >0 # do not display error type in "Q" (quiet) mode _Error() { # errormsg [errorlevel|"q" [errorlevel]] local ER ret case "${2:-1}" in [1-9]*) ER="ERROR"; ret="${2:-1}" ;; [0Ii]*) ER="INFO"; ret=0 ;; [-Ww]*) ER="WARNING"; ret=-1 ;; [Qq]*) ER=""; ret="${3:--1}";; *) ER="ERROR"; ret=1 ;; esac if [ "$_Verb" -ge 1 ] # verbose then __Message "$1" "$ER" elif [ "$_Verb" -ge 0 ] # normal then test "$ret" -eq 0 || __Message "$1" "$ER" >&2 else # quiet test "$ret" -le 0 || __Message "$1" "$ER" >&2 fi test $ret -le 0 || exit $ret } # Display a message to stderr _Msg() { # [message] _Error "${*:-}" q } ################################################ # Temporary files and exit handler # Remove all temporary files and directory _clean_tmp() { local F test -z "$_TmpFiles" || echo "$_TmpFiles" | while read F do test -z "$F" || rm -f "$F"; done test -z "$_TmpDirs" || echo "$_TmpDirs" | while read F do case "$F" in */tmp/?*) # it seems safe to delete this rm -rf "$F";; "") ;; *) _Error "It seems unsafe to delete '$F' directory" w ;; esac done _TmpDirs=""; _TmpFiles="" } __cleanup_handler() { # [exit status] trap - EXIT _clean_tmp exit "$1" } # Perform actions on exit _exit_handler() { __cleanup_handler "$?" } # Perform actions on deadly signal and exit _signal_handler() { __cleanup_handler 143 # SIGTERM+128 } trap _exit_handler EXIT trap _signal_handler HUP INT QUIT PIPE TERM # create a temporary file and store its name to _TmpFiles # second parameter: [-]d* -- directory, [-]p* -- pipe, other -- file # assign filename to "variable" _TmpFile() { # variable [type] local _F _P _Z _N="file" case "$1" in *[!_a-zA-Z0-9]*) _Error "Cannot store valuse to '$1' variable, please user alphanumeric name" ;; "") _Error "no variable name provided to _TmpFile function" ;; esac case "$2" in *p|p*) _P=""; _N="pipe";; *d|d*) _P="-d"; _N="directory";; esac _F=`mktemp -t $_P $_AMe.$_N.XXXXXXXXXXXX` || _Error "Cannot create '$_F' temporary $_N" case "$2" in *p|p*) # XXX look for race conditions here _Z="`mktemp XXXXXXXXXXXX`" mv "$_F" "$_Z" mkfifo "$_F" rm -f "$_Z" ;; esac case "$_N" in directory) _TmpDirs="$_TmpDirs $_F" ;; *) _TmpFiles="$_TmpFiles $_F" ;; esac eval "export $1='$_F'" } # create a temporary directory and store its' name to _TmpDirs # assign filename to "variable" _TmpDir() { # variable _TmpFile "$1" directory } ################################################ # Help system # TODO long options # WARNING: this function strongly depends on "case" operator programming style: # key) # help string # if help string contains capitalized word, it will be used as parameter name # E. g.: # o) # redirect output to FILE # will produce this help string: # -o FILE redirect output to FILE # By default, help strings are searched # from the first occurance of " getopts " string to the first " esac$" pattern # so keep a commentary after additional "esac" if it emerges inside # # Generted varsiables: # _Options -- option string in getopts format # Store a help information _MakeHelp() { # description [tail_text [additional_help [start_pattern end_pattern]]] local descr local selfname case "$1" in *--*) selfname="${1%% -- *}"; descr="${1##* -- }" ;; ?*) selfname="$_Me"; descr="$1" ;; "") _Error "Insufficient parameters in _MakeHelp" ;; esac local st="${4:-" getopts "}" local en="${5:-"[ ]esac[ ]*$"}" local sedfilter="/$st/,/$en/" local sedFpattern='^[ ]*\([^)]*\))[ ]*#[ ]*\(.*\)' local sedUpattern='^[ ]*\([^)]*\))[ ]*#[ ]*![ ]*\(.*\)' local sedPpattern='^[ ]*\([^)]*\))[ ]*#[ ]*\([^!]*[^!A-Z]\([A-Z]\{3,\}\).*\)' local genhelp="$(sed -n "$sedfilter{ /$sedPpattern/s/$sedPpattern/\t-\1 <\3>\t\2/p /$sedUpattern/s/$sedUpattern/(TODO)\t-\1\t\t\2/p /$sedFpattern/s/$sedFpattern/\t-\1\t\t\2/p }" "$_FMe")" _Options=$(sed -n "$sedfilter{ /$sedPpattern/s/$sedPpattern/\1:/p /$sedUpattern/n /$sedFpattern/s/$sedFpattern/\1/p }" "$_FMe" | tr -d '\n') _Usage="$selfname v$_Version -- $descr Usage: $_Me [-$_Options]${2:+" "}$2" _Help=" $genhelp${3:+$__CR}$3" } ################################################ # Configuration file editing # Set "Variable=Value" inside Context of File or append it at the start of the Context _CfgEqSet() { # File Variable Value [Context=0,$] local Context="${4:-1,\$}" N=$(sed -n "$Context{/^[ ]*$2[ ]*=/=}" "$1") # if Variable=Value exists test -n "$N" && for n in $N do # Replace sed -i "$n""s/^\([ ]*$2[ ]*=[ ]*\).*/\1$(_Quote "$3")/" "$1" done || { # Append N=$(sed -n "$Context{=;q}" "$1") test -n "$N" && sed -i "$N""a\ $2=$3 " "$1" || _Error "No '$Context' context found in $1" -1 } } __CfGet() { # File Context Variable Div Value Tail test -z "$(sed -n "$2{=}" "$1")" && _Error "No '$2' context found in $1" -1 || { local ret=$(sed -n "$2{/$3$4$5$6/{s/$3$4\($5\)$6/\1/p;q}}" "$1") echo -n $ret test -n "$ret" } } # Print Value from "Variable=Value" inside Context of File _CfgEqGet() { # File Variable [Context=1,$] __CfGet "$1" "${3:-1,\$}" "^[ ]*$2" "[ ]*=[ ]*" ".*" "" } # Print Value from "Variable Value" inside Context of File _CfgBlGet() { # File Variable [Context=1,$] __CfGet "$1" "${3:-1,\$}" "^[ ]*$2" " *" ".*" "" } # Delete all "Variable=" entries inside Context of File _CfgEqDel() { # File Variable [Context=1,$] local Context="${3:-1,\$}" test -z "$(sed -n "$Context{=}" "$1")" && _Error "No '$Context' context found in $1" -1 || sed -i "$Context{/^[ ]*$2[ ]*=/d}" "$1" } # Comment all "Variable=" entries inside Context of File _CfgEqComm() { # File Variable [Context=1,$] local Context="${3:-1,\$}" test -z "$(sed -n "$Context{=}" "$1")" && _Error "No '$Context' context found in $1" -1 || sed -i "$Context{s/^\([ ]*$2[ ]*=.*\)/#\1/}" "$1" } # Uncomment all "#Variable=" entries inside Context of File _CfgEqUnComm() { # File Variable [Context=1,$] local Context="${3:-1,\$}" test -z "$(sed -n "$Context{=}" "$1")" && _Error "No '$Context' context found in $1" -1 || sed -i "$Context{s/^[ ]*#\([ ]*$2[ ]*=.*\)/\1/}" "$1" } ################################################ # Parallel execution functions # To run a number of tasks in parallel: # first call _II_init # next call _II_run [] for each task # and last call _II_wait to wait for last task to be done # Detect number of cores _II_cores() { # N="`ls -d /proc/sys/kernel/sched_domain/cpu* 2>/dev/null | wc -l`" || N="`sysctl -n kern.smp.cpus 2>/dev/null`" test -z "$N" && _Msg "Warning: cannot determine number of CPUs" echo "$(($N+0))" } # Initialize parallel environment for running maxproc tasks at once _II_init() { # [maxproc] _TmpFile __II_count # number of processes _TmpFile __II_sync pipe # pipe for end-of-proc catching __II_maxproc="${1:-$(_II_cores)}" # parallel slots number __II_current=0 # tasks already executed } __II_done() { wc -l < $__II_count; } __II_exit() { trap - EXIT echo $__II_err >> $__II_count echo $__II_err > $__II_sync exit $__II_err } ___II_next() { o.par2sat.sh $__II_sync $__II_count "$@" } __II_next() { __II_err=0 trap __II_exit EXIT "$@" __II_err="$?" } __II_pause() { { read __II_err < $__II_sync; } 2>/dev/null || :; } # Wait for empty slot becomes available, then execute a task _II_run() { # task [args ...] test $(($__II_current - $(__II_done) )) -lt $__II_maxproc || __II_pause (__II_next "$@") & __II_current=$(($__II_current + 1)) } # Wait for all tasks to be done _II_wait() { while test $(($__II_current - $(__II_done) )) -ne 0 do __II_pause; done } ################################################ # XTerm voodoo export __XT="" # XTerm voodoo text container # Tackle XTerm to push response on string (e. g. ^[]50;?^G respond with fontname) _XTResponse() { # string [tty] # XXX: using any tty instead of /dev/tty is not work local STTY DTTY="${2:-/dev/tty}" STTY=`stty -g < "$DTTY"` stty raw -echo < "$DTTY" echo -n "$1" > "$DTTY" test -n "$__XT" || _TmpFile __XT cat < "$DTTY" > "$__XT" 2>/dev/null & stty < "$DTTY" > /dev/null 2>&1 # pause kill $! > /dev/null 2>&1 stty $STTY < "$DTTY" cat "$__XT" } ################################################ # Misc functions # TODO: "A_b_c" "D_e" -> "A b c" "D e" call # print pseudo-random 0..Max (32767 if Max undefined) _Random() { # [Max] echo $((`dd if=/dev/urandom count=2 bs=1 2>/dev/null | od -An -t u4`%${1:-32768})) } # parse "ipcalc Parameters" and get Field value _IpCalc() { # Parameters Field ipcalc $1 | sed -n "/$2/s/$2[ ][ ]*\([^ /]*\).*/\1/p" } # decode utf-8 output if not utf-8 locale is used _DeU8() { # [locale] local l="${1:-$LANG}" case "$l" in *[uU][Tt][fF]*8*) cat ;; *) iconv -f utf-8 -t "${l##*.}" -r. ;; esac } # remove arg from argument_string _DelArg() { # argument_string arg local a=" $1 " a="${a% $2 *} ${a#* $2 }" a="${a% }"; a="${a# }" echo "$a" } # translate string of format "3-5,12,15" to "3 4 5 12 15" and print it _ExpandEnum() { # number_list [divider [diapazone_divider]] local div="${2:-,}" local dia="${3:--}" local d n for d in $(echo "$1" | tr "$div" " "); do case "$d" in *-*) for n in $(seq $(echo "$d" | tr "-" " ") ); do echo $n; done ;; *) echo "$d" ;; esac done } # quote Chars_regexp in Str (e. g. /home/dir -> \/home\/dir) _Quote() { # Str [Chars_regexp="[/]"] echo "$1" | sed "s@\(${2:-[/]}\)@\\\\\1@g" } # use this to cat the stdin and echo args instead of running filter-like program _CatEcho() { # [text] # TODO: prog name or something tty -s || cat echo " $@" } case "$_GMe" in functions|*.functions) # directly called echo "$_GMe v$__Version" >&2 tty -s && PG=less || PG=cat sed -n '/^__/d /^_/p /^[ ]*$/p /^#[^!]/p /^export _/s/^export \(_[^ = ,]*\)[^#]*#[ ]*\(.*\)/\1\t\2/p ' "$_FMe" | $PG ;; esac nish-functions-0.5/functions.locate000075500000000000000000000002431112243173600175260ustar00rootroot00000000000000#!/bin/sh # You can modify this depending on where functions files are stored __LIBEXEC="$(dirname "$(realpath "$0")")" echo "$__LIBEXEC/$(basename "$0" .locate)"