############################################################################## # BASE ENV ############################################################################## TOOLS=$(cd $(dirname -- $0) && pwd) PATH=$TOOLS:/usr/local/symlinks:$PATH export PATH TOOLS umask 0022 if ${HTMLREPORTING:-false} then V_BOLD="" V_REVERSE="$V_BOLD" V_UNDERLINE="" V_VIDOFF_BOLD="" V_VIDOFF_REVERSE="$V_VIDOFF_REVERSE" V_VIDOFF_UNDERLINE="" elif [ -t 1 ] then ## Set some video text attributes for use in error/warning msgs V_REVERSE='' V_UNDERLINE='' V_BOLD='' [ -f /usr/bin/tput ] && V_BLINK=$(tput blink) V_VIDOFF='' V_VIDOFF_REVERSE="$V_VIDOFF" V_VIDOFF_BOLD="$V_VIDOFF" V_VIDOFF_UNDERLINE="$V_VIDOFF" fi export V_REVERSE V_UNDERLINE V_BOLD V_BLINK V_VIDOFF # Set some usable highlighted keywords for functions like OkFailed(). OK="${V_BOLD}OK$V_VIDOFF_BOLD" FAILED="${V_REVERSE}FAILED$V_VIDOFF_REVERSE" WARNING="${V_REVERSE}WARNING$V_VIDOFF_REVERSE" YES="${V_BOLD}YES$V_VIDOFF_BOLD" NO="${V_REVERSE}NO$V_VIDOFF_REVERSE" # Set REALUSER #REALUSER=`id -nu` #export REALUSER # Set a PID for use throughout PID=$$;export PID # Save original cmd-line ORIG_CMDLINE="$*" # Define some functions when sourced from PROGrams #[ -n "$PROG" ] && . stdlib.sh # set a basic trap to capture ^C's and other unexpected exits and do the # right thing in TrapClean(). trap TrapClean 2 3 15 ############################################################################## # Standard library of useful shell functions and GLOBALS ############################################################################## # Define logecho() function to display to log and std out # Args can be -n or -r or -nr or -rn ONLY. # -r = raw output - no $PROG: prefix # -n - no newline (just like echo -n) logecho () { # Dynamically set fmtlen local lfmtlen= let lfmtlen=80-${#PROG} N= raw=false case "$1" in -n) N=-n shift ;; -r) raw=true shift ;; -rn|-nr) N=-n;raw=true shift ;; esac # Allow widespread use of logecho without having to # determine if $LOGFILE exists first. # # If -n is set, do not provide autoformatting or you lose the -n affect # Use of -n should only be used on short status lines anyway. if [ ! -f "$LOGFILE" ] then if $raw then echo $N "$*" elif [ "$N" = -n ] then echo $N "$PROG: $*" else # To create a line continuation character #echo $N "$*" |fmt -$lfmtlen |sed -e "1s,^,$PROG: ,g" -e "2,\$s,^,$PROG: .,g" echo $N "$*" |fmt -$lfmtlen |sed "s,^,$PROG: ,g" fi else if $raw then echo $N "$*" | tee -a $LOGFILE elif [ "$N" = -n ] then echo $N "$PROG: $*" | tee -a $LOGFILE else # To create a line continuation character #echo $N "$*" |fmt -$lfmtlen |sed -e "1s,^,$PROG: ,g" -e "2,\$s,^,$PROG: .,g" | tee -a $LOGFILE echo $N "$*" |fmt -$lfmtlen |sed "s,^,$PROG: ,g" | tee -a $LOGFILE fi fi } logrun () { # if no args, take stdin if [ -z "$1" ] then if ${VERBOSE:-true} then tee -a $LOGFILE else tee -a $LOGFILE > /dev/null 2>&1 fi elif [ -f "$LOGFILE" ] then echo >> $LOGFILE echo "CMD: $*" >> $LOGFILE # Special case for "cd" which cannot be run through a pipe (subshell) if ${VERBOSE:-true} && [ "$1" != cd ] then ${*:-:} 2>&1 | tee -a $LOGFILE return ${PIPESTATUS[0]} else ${*:-:} >> $LOGFILE 2>&1 fi else if ${VERBOSE:-false} then $* else $* >/dev/null 2>&1 fi fi } OkFailed () { if logrun $* then logecho -r $OK else logecho -r $FAILED return 1 fi } # Define process output ProcessOutput () { if ${VERBOSE:-true} then tee -a $LOGFILE else tee -a $LOGFILE > /dev/null 2>&1 fi } GeneratePassword () { dd if=/dev/urandom count=1 2> /dev/null | uuencode -m - | sed -ne 2p | cut -c-8 } # TimeStamp < begin | end | done > [ section ] #+ DESCRIPTION #+ TimeStamp begin is run at the beginning of the script to display a #+ 'begin' marker and TimeStamp end is run at the end of the script to #+ display an 'end' marker. #+ TimeStamp will auto-scope to the current shell or you can optionally #+ pass in a second argument as a section identifier if you wish to track #+ multiple times within the same shell. #+ #+ For example, if you call TimeStamp begin and end within one script and then #+ call it again in another script (new shell), you can just use begin and end #+ But if you want to call it twice within the same script use it like this: #+ TimeStamp () { # Always set trace (set -x) back #set +x # action=$1 section=${2:-run} # convert / to underscore section=${section//\//_} # convert : to underscore section=${section//:/_} # convert . to underscore section=${section//./_} case "$action" in begin) # Get time(date) for display and calc eval ${section}start_seconds=$(date '+%s') # Print BEGIN message for $PROG logecho "BEGIN $section on ${HOSTNAME%%.*} $(date)" [ "$section" = run ] && logecho -r ;; end|done) # Check for "START" values before calcing if [ -z "$(eval echo \\$\"${section}start_seconds\")" ] then #display_time="EE:EE:EE - 'end' run without 'begin' in this scope or sourced script using TimeStamp" return 1 else # Get time(date) for display and calc eval ${section}end_seconds=$(date '+%s') # process time start_display_time=$(eval echo \$"${section}start_seconds") # if start time is blank then just exit... [ -z "$start_display_time" ] && return 0 end_display_time=$(eval echo \$"${section}end_seconds") display_time=$(expr ${end_display_time} - ${start_display_time:-0} |\ awk '{ in_seconds=$0 days=in_seconds/86400 remain=in_seconds%86400 hours=remain/3600 remain=in_seconds%3600 minutes=remain/60 seconds=remain%60 printf("%dd %02d:%02d:%02d\n",days, hours, minutes, seconds) }') fi [ "$section" = run ] && logecho -r # To override logecho's 80-column limit, echo directly and pipe to logrun # for verbose/log handling echo "$PROG: DONE $section on ${HOSTNAME%%.*} $(date) ${V_BOLD}in $display_time$V_VIDOFF_BOLD" |VERBOSE=true logrun # NULL these local vars unset ${section}start_seconds ${section}end_seconds ;; esac } TrapClean () { # If user ^C's at read then tty is hosed, so make it sane again stty sane logecho -r logecho -r logecho "^C caught!" Exit 1 "Exiting..." } CleanExit () { # cleanup CLEANEXIT_RM # Sanity check the list # should we test that each arg is a absolute path? if echo "$CLEANEXIT_RM" |fgrep -qw / then logecho "/ found in CLEANEXIT_RM. Skipping Cleanup..." else if [ -n "$CLEANEXIT_RM" ] then logecho "Cleaning up:$CLEANEXIT_RM" else : logecho "Cleaning up..." fi # cd somewhere relatively safe and run cleanup the $CLEANEXIT_RM stack # + some usual suspects... cd /tmp && rm -rf $CLEANEXIT_RM $TMPFILE1 $TMPFILE2 $TMPFILE3 $TMPDIR1 \ $TMPDIR2 $TMPDIR3 fi # display end timestamp when an existing TimeStamp begin was run [ -n "$runstart_seconds" ] && TimeStamp end exit ${1:-0} } # Requires 2 args # - Exit code # - message Exit () { local etype=${1:-0} shift logecho -r logecho $* logecho -r CleanExit $etype } # these 2 kept for backward compat for now Exit0 () { Exit 0 $* } Exit1 () { Exit 1 $* } Askyorn () { local yorn case "$1" in -y) # yes default shift logecho -n "$* ([y]/n)? " read yorn case "$yorn" in [nN]) return 1 ;; *) return 0 ;; esac ;; *) # no default case "$1" in -n) shift ;; esac logecho -n "$* (y/[n])? " read yorn case "$yorn" in [yY]) return 0 ;; *) return 1 ;; esac ;; esac } ############################################################################## netls () { url=${1:-"http://build/packages/kernel/experimental/autotest"} wget -O - $url 2>&1 |sed -ne '/Parent Directory/,/^$/p' | sed 's,<[^>]*> *,,g' |sed -ne '2,$p' |sed '/^$/d' } Spinner () { while true do echo -n "-" sleep 1 echo -n "\\" sleep 1 echo -n "|" sleep 1 echo -n "/" sleep 1 done } # Takes a step number and a string and prints out a section header # If the first arg isn't a number, then it just prints the string StepHeader () { if [[ "$1" == [0-9]* ]] then local step="STEP $1 - " shift fi local msg=$* logecho -r echo -n $V_BOLD logecho "================================================================" logecho "$step$msg" logecho "================================================================" echo -n $V_VIDOFF_BOLD logecho -r } LogfileInit () { local lnum=$2 # Initialize Logfile # only set and shift(savefile) LOGFILE If none was set by calling program if [ -z "$LOGFILE" ] then LOGFILE=${1:-$(pwd)/$PROG.log} savefile file=$LOGFILE num=${lnum:-3} rm=yes echo "CMD: $PROG $ORIG_CMDLINE" >$LOGFILE else echo "CMD: $PROG $ORIG_CMDLINE" >>$LOGFILE fi } CanonicalizePath () { [ -z "$1" ] && return cd -P -- "$(dirname -- "$1")" && printf '%s\n' "$(pwd -P)/$(basename -- "$1")" } ##################################################################### # Set BUGSHELL_PASSWORD ##################################################################### BugshellAuth () { # XXX: Buganizer and SSO. There's no solution yet that will allow # password-less access to buganizer, so prompt for password each run. (awful) # nmlorg trying to fix this: http://b/issue?id=759835 # If I ever want to encrypt this: #encrypted_password=$(echo $buganizer_password |openssl des3 -a -k $cryptkey) #decrypted_password=$(echo "$encrypted_password" |openssl des3 -d -a -k $cryptkey) # Try to get a password from local machine local ldap_password_file=/usr/local/google/$USER/.password BUGANIZER_PASSWORD=$(cat $ldap_password_file 2>&-) until $BUGSHELL --password $BUGANIZER_PASSWORD ls 2>&- do echo read -s -p "$PROG: Access to Buganizer required. Enter your LDAP password: " BUGANIZER_PASSWORD echo done if [ "$(cat $ldap_password_file 2>&-)" != $BUGANIZER_PASSWORD ] then if Askyorn "Store your password (600) in $ldap_password_file" then mkdir -p $(dirname $ldap_password_file) echo $BUGANIZER_PASSWORD > $ldap_password_file chmod 600 $ldap_password_file fi fi } # Takes space separated list of elements and returns a random one PickRandomElement () { # array of strings local llist=($@) local lrange= local lrand=$RANDOM # set range lrange=${#llist[*]} # set boundaries let "lrand %= $lrange" #echo "Random number less than $lrange --- $lrand = ${llist[$lrand]}" echo ${llist[$lrand]} } # It creates a temporary file to expand the environment variables ManHelp () { # Whatever caller is local lprog=$0 local ltmpfile=/tmp/$PROG-manhelp.$$ # Standard usage function if [ "x$usage" = "xyes" -o "x$1" = "x-usage" -o \ "x$1" = "x--usage" -o "x$1" = "x-?" ] then echo 'cat << EOFCAT' >$ltmpfile echo "Usage:" >> $ltmpfile sed -n '/#+ SYNOPSIS/,/^#+ DESCRIPTION/p' $lprog |\ sed -e 's,^#+ ,,g' -e '/^DESCRIPTION/d' >> $ltmpfile echo "EOFCAT" >> $ltmpfile . $ltmpfile rm -f $ltmpfile exit 1 fi # Standard man function if [ "x$man" = "xyes" -o "x$1" = "x-man" -o \ "x$1" = "x--man" -o "x$1" = "x-help" -o "x$1" = "x--help" ] then echo 'cat << EOFCAT' >$ltmpfile grep "^#+" $lprog |cut -c4- >> $ltmpfile echo "EOFCAT" >> $ltmpfile . $ltmpfile | ${PAGER:-"less"} rm -f $ltmpfile exit 1 fi # Standard comments function if [ "x$comments" = "xyes" -o "x$1" = "x-comments" ] then echo egrep "^#\-" $lprog |sed -e 's,^#- *,,g' rm -f $ltmpfile exit 1 fi } # parse cmdline # Run namevalue as a separate script so it can handle quoted args --name="1 2" . namevalue # Run ManHelp to show usage and man pages ManHelp $@ # Keep crostools up to date # symlink may be setting by caller or use $0 # Try it using std git pull or repo sync (cd $(dirname ${symlink:-$0}) && git pull -q >/dev/null 2>&1 ||\ repo sync crostools > /dev/null 2>&1)