#!/bin/sh # samlt aka truc # http://sam.intelunix.fr/sampm/ VERSION=20081114 # md5sum of the ~/.bashrc-sampm file if you set specific fonctions/alias for him.. # If you don't the file will be generated on each run, so it won't hurt anyway MD5SUM_PMPLAYER_OK=e69d0c504cfd47a8e4953b3229c61cb0 MD5SUM_PMADMIN_OK=f3c7fcbacfa3134c44f8ddd320af5503 MD5SUM_OK=b1429273b99a3acc3afc8f1ebdded9ff PROGNAME="$0" WHOAMI=$(whoami) LOSETUP=/sbin/losetup CRYPTSETUP=/sbin/cryptsetup umask 077 # backup {{{ function backup () { local lastMonth lastMonthLastBkp echo "Backup'ing..." mkdir -p $HOME/pmBackup cp $HOME/${WHOAMI}DB.img $HOME/pmBackup/$(date +%Y-%m-%d)-${WHOAMI}DB.img || { echo "Are you sure this has ever worked for this user? Exiting..." ; exit 1 ; } cd $HOME/pmBackup lastMonth=$(date -d 'last month' +'%Y-%m') lastMonthLastBkp=$(ls -1t ${lastMonth}-[0-9][0-9]-${WHOAMI}DB.img 2>/dev/null | head -n 1) [ ! -z "$lastMonthLastBkp" ] && mv -v -- $lastMonthLastBkp ${lastMonth}-${WHOAMI}DB.img rm -vf -- ${lastMonth}-[0-9][0-9]-${WHOAMI}DB.img } # }}} # find loop {{{ function findLoop () { local dev found= for dev in /dev/loop*; do $LOSETUP $dev 2>/dev/null | grep -xq "${dev}:[[:space:]].\+[[:space:]]($HOME/${WHOAMI}DB.img)" [ 0 -eq $? ] && { echo $dev ; return 0 ; } done return 1 } # }}} LOOPDEV=$(findLoop) # check_and_setup {{{ # LUKS device opened? function check_and_setup () { local LS IMG ret if [ ! -b /dev/mapper/${WHOAMI}DB ]; then # loopdevice exist? if [ -z "$LOOPDEV" ]; then LOOPDEV=$($LOSETUP -f) if [ -z "$LOOPDEV" ]; then echo "Can't find a usable loop device (/dev/loop*)..." echo "You can create one with something like: 'mknod /dev/loop5 b 7 5'" echo "Can't continue." exit 2 fi # mounting the loop file IMG=$HOME/${WHOAMI}DB.img if [ ! -r "$IMG" ]; then echo "$IMG doesn't exist? You're on your own there..." exit 3 fi sudo ${LOSETUP} $LOOPDEV $HOME/${WHOAMI}DB.img # checking... {{{ LS=$(${LOSETUP} $LOOPDEV 2>/dev/null) LS="${LS##*(}" LS="${LS%%)*}" if [[ "$HOME/${WHOAMI}DB.img" != "$LS" ]]; then echo "Can't 'mount' the loop file $IMG... Fix it!" exit 3 fi # }}} fi # Opening luks device {{{ # checking it's really a luks device ${CRYPTSETUP} isLuks $LOOPDEV 2>&1 >/dev/null ret=$? [ 0 -ne $ret ] && { echo "$LOOPDEV not a LUKS device. Not my fault, fix it." ; exit 4 ; } # Opening the luks device sudo ${CRYPTSETUP} luksOpen $LOOPDEV ${WHOAMI}DB ret=$? [ 0 -ne $ret ] && { echo "Forgot the password? ;)" ; exit 5 ; } # }}} fi # luks opened, partition mounted? mount | grep -q "/dev/mapper/${WHOAMI}DB[[:space:]]\+on[[:space:]]\+${HOME}/${WHOAMI}DB[[:space:]]\+type[[:space:]]\+ext2[[:space:]](r" if [ "$?" -ne 0 ]; then # not! mounting it sudo mount /dev/mapper/${WHOAMI}DB ret=$? [ 0 -ne $ret ] && { echo "Did you modify the fstab according to the wiki page?" ; exit 7 ; } fi } # }}} # forceStop () {{{ function forceStop () { local PIDs echo "stopping...[forced]" echo "killing other ${PROGNAME##*/} processes..." PIDs=$(pgrep -f -- "/bin/bash --rcfile $HOME/.bashrc-sampm") [ ! -z "$PIDs" ] && kill -9 $PIDs 2>/dev/null sleep 3 [ -b /dev/mapper/${WHOAMI}DB ] && { sudo umount /dev/mapper/${WHOAMI}DB && sudo ${CRYPTSETUP} luksClose ${WHOAMI}DB ; } sudo ${LOSETUP} -d $LOOPDEV } # }}} # softStop () {{{ function softStop () { local NB myUID=$(awk -v FS=':' '$1 == "'"$WHOAMI"'" { print $3 }' /etc/passwd) echo "[soft]stopping.." NB=$(pgrep -u $myUID -cf "sh[[:space:]]+$PROGNAME") if [ 1 -lt $NB ]; then echo "There are other ${PROGNAME##*/} instances... keeping the DB untouched, exiting.." else echo "No other ${PROGNAME##*/} instance, umounting..." [ -b /dev/mapper/${WHOAMI}DB ] && { sudo umount /dev/mapper/${WHOAMI}DB ; sudo ${CRYPTSETUP} luksClose ${WHOAMI}DB ; } > /dev/null 2>&1 sudo ${LOSETUP} -d $LOOPDEV > /dev/null 2>&1 # checking everything went right mount | grep -q "/dev/mapper/${WHOAMI}DB[[:space:]]\+on[[:space:]]\+${HOME}/${WHOAMI}DB[[:space:]]\+type[[:space:]]\+ext2[[:space:]](r" if [ "$?" -eq 0 ]; then echo "The DB is still mounted, you should check manually why I could not umount it" fi fi } # }}} # exporttrm {{{ function exporttrm () { # if the loop file isn't mounted&decrypted, we stop (so that this work even in a cron job, # without waiting forever for the password to be entered mount | grep -q "/dev/mapper/${WHOAMI}DB[[:space:]]\+on[[:space:]]\+$HOME/${WHOAMI}DB[[:space:]]\+type[[:space:]]\+ext2[[:space:]](r" if [ "$?" -ne 0 ]; then echo -e "the encrypted loopfile isn't mounted, I can't continue\nExiting..." exit 1 fi USER=$WHOAMI /bin/bash --rcfile $HOME/.bashrc-sampm -i -c "samexport $1" > "$2" } # }}} # checkrc {{{ function checkrc () { local fixme=0 MD5SUM MD5SUM=$(md5sum "$1" 2>/dev/null) [ -z "$1" -o ! -r "$1" ] && MD5SUM=blablalba MD5SUM=${MD5SUM%% *} case "$WHOAMI" in pmplayer) [[ "$MD5SUM" == "$MD5SUM_PMPLAYER_OK" ]] || fixme=1 ;; pmadmin) [[ "$MD5SUM" == "$MD5SUM_PMADMIN_OK" ]] || fixme=1 ;; *) [[ "$MD5SUM" == "$MD5SUM_OK" ]] || fixme=1 ;; esac if [ 1 -eq "$fixme" ]; then echo "~${USER}/.bashrc-sampm has changed, regenerating it" # Not ok {{{ cat <<'EOF' > "$1" # Ok, this is a very basic trick, just to avoid one making unwanted actions : ${zAWK:=$(which awk)} : ${zCAT:=$(which cat)} : ${zCP:=$(which cp)} : ${zDATE:=$(which date)} : ${zFIND:=$(which find)} : ${zGREP:=$(which grep)} : ${zHEAD:=$(which head)} : ${zLS:=$(which ls)} : ${zMKDIR:=$(which mkdir)} : ${zMOUNT:=$(which mount)} : ${zMOVE:=$(which mv)} : ${zRM:=$(which rm)} : ${zRMDIR:=$(which rmdir)} : ${zSED:=$(which sed)} : ${zSORT:=$(which sort)} : ${zSUDO:=$(which sudo)} : ${zTR:=$(which tr)} : ${zW:=$(which w)} : ${zWC:=$(which wc)} : ${zWHO:=$(which who)} # aliases {{{ for cmd in bg bind caller command declare dirs disown enable eval exec export false fc fg \\ getopts hash history jobs kill let popd pushd readonly select set shopt source \\ suspend test time times true type typeset ulimit umask unalias unset until wait ; do alias $cmd=help done alias vim="echo 'huhu, nono, use edit instead'" alias :w="echo 'Hey man! Pay attention to what you are doing!'" alias :wq="echo 'Wake up Neo! It's real life there, you can't do that!'" # }}} function _is_DB_rw () { # {{{ ${zMOUNT} | ${zGREP} -q "/dev/mapper/${USER}DB[[:space:]]\+on[[:space:]]\+${DB}[[:space:]]\+type[[:space:]]\+ext2[[:space:]](rw," } # }}} function _need_DB_rw () { # {{{ _is_DB_rw || { echo "You need to set the database Read-Write (with _setDB_rw) before you can continue"; return 1; } # DB is Read-Write [ ! -r ${DB}.lock ] && > ${DB}.lock local lock=$(< ${DB}.lock) # MEFROM is defined in the ~/.bashrc-sampm if [ -z "$lock" ]; then echo "Someone is already editing the database, try later(lock file not correct, can't tell more)" elif [[ "$lock" != "$MEFROM" ]]; then echo -e "The DB is already set Read-Write by '\e[1m${lock##* }\e[22m' on '\e[1m${lock%% *}\e[22m', try later, or beat him to death" return 1 fi # OK return 0 } # }}} function _setDB_rw () { # {{{ if _is_DB_rw; then [ ! -r ${DB}.lock ] && > ${DB}.lock local lock=$(< ${DB}.lock) # MEFROM is defined in the ~/.bashrc-sampm if [ -z "$lock" ]; then echo "Someone is already editing the database, try later(lock file not correct, can't tell more)" return 1 fi if [[ "$lock" != "$MEFROM" ]]; then # may be we'll find this is a good idea? anyway this is disabled for now #if [ -z "$1" -a "$1" != "--force" ]; then # echo "DB already RW, --force specified, modifying the lock file to reflect *you* are not editing" #fi echo -e "The DB is already set Read-Write by '\e[1m${lock##* }\e[22m on \e[1m${lock%% *}\e[22m', try later, or beat him to death" return 1 else echo "You already have mounted the DB Read-Write?!" return 0 fi else ${zSUDO} ${zMOUNT} -o remount,rw,nodev,noexec,noauto,sync /dev/mapper/${USER}DB [ $? -eq 0 ] && echo $MEFROM > ${DB}.lock fi } # }}} function _setDB_ro () { # {{{ local lock if ! _is_DB_rw ; then ${zRM} -rf ${DB}.lock echo "${USER}DB is not mounted read-write. Nothing to do!" return 0 else # First we need to check who mounted the DB RW [ ! -r ${DB}.lock ] && > ${DB}.lock lock=$(< ${DB}.lock) # MEFROM is defined in the ~/.bashrc-sampm if [ -z "$lock" ]; then echo "the lock file isn't correct, ignoring it" elif [[ "$lock" != "$MEFROM" ]]; then if [ -z "$1" -a "$1" != "--force" ]; then echo "You can't set the DB Read-Only if it's not you who set it Read-Write, unless you force it with --force" return 3 fi fi ${zSUDO} ${zMOUNT} -o remount,ro,nodev,noexec,noauto,sync /dev/mapper/${USER}DB ${zRM} -rf ${DB}.lock fi } # }}} function cd () { # {{{ local ret=0 if [ $# -lt 1 ]; then builtin cd "${DB}" >/dev/null else builtin cd "$1" >/dev/null ret=$? # outside of the DB? [[ ${PWD#${DB}} == $PWD ]] && { builtin cd "${DB}" >/dev/null ; ret=1 ; } fi LPWD=${PWD#${DB}} LPWD=${LPWD#/} return $ret } # }}} function cp () { # {{{ # if destination is 'supposed' to be a file, check its name is correct # 'supposed': # if exactly two arguments, and if $1 is a file, $2 is either an existing # directory or a 'new' file if [ 2 -eq $# -a -f "$1" -a ! -d "$2" ]; then # check the filename is correct if ! _checkfilename "$2" ; then echo "These are the only characters allowed for the title: [A-Za-z0-9@=_.-]" echo "Action cancelled..." return 1 fi fi _need_DB_rw || return 1 ${zCP} -iv "${@}" } # }}} function mv () { # {{{ # Same logic as in the 'cp' function: if [ 2 -eq $# -a -f "$1" -a ! -d "$2" ]; then # check the filename is correct if ! _checkfilename "$2" ; then echo "These are the only characters allowed for the title: [A-Za-z0-9@=_.-]" echo "Action cancelled..." return 1 fi fi _need_DB_rw || return 1 ${zMOVE} -iv -- "${@}" } # }}} function mkdir () { # {{{ _need_DB_rw || return 1 ${zMKDIR} -pv "${@// }" } # }}} function pwd () { # {{{ LPWD=${PWD#${DB}} LPWD=${LPWD#/} echo ${LPWD} } # }}} function rm () { # {{{ _need_DB_rw || return 1 ${zRM} -iv "${@}" } # }}} function rmdir () { # {{{ _need_DB_rw || return 1 ${zRMDIR} -v "${@}" } # }}} # Due to how _checkfilename works, it can only validates file in CWD function _checkfilename () { # {{{ ${zGREP} -Gqx '[A-Za-z0-9@=_.+-]\+' <<< "$1" } # }}} function _checkfile () { # {{{ _checkfilename "$1" || { echo NOK ; return 1; } ${zSED} -rn ' 1{ /^Username: ./!berror b } 2{ /^URL: ./!berror b } 3{ /^Password: /!berror b } 4{ /^Notes: /!berror } a \ OK # quit after that q :error # on all other cases, the file is wrong a \ NOK q ' "${1}" 2>/dev/null || echo NOK } # }}} function _file_ok () { # {{{ [[ "OK" == $(_checkfile "$1") ]] } # }}} function _show_info_from_file () { # {{{ for file do [ -f "${file}" -a -r "${file}" ] || continue _checkfilename "${file##*/}" || continue printf " %-45s\t" ${file##*/} <"${file}" ${zSED} -rn ' 1{ s/^Username: (.)/\1/ Terror # to align the URLs in the output s/$/ / s/^(.{25}).*/\1/ h b } 2{ s/^URL: (.)/\1/ Terror H x s/\n//p q } :error a\ !!! incorrect password file !!! q ' done } # }}} function ls () { # {{{ local arg dir username URL Notes Password nb local recursive=0 [[ "-rx" == "$1"x ]] && { recursive=1 ; shift ; } for arg in "${@:-.}"; do if [ -f "$arg" -a -r "$arg" ]; then echo "$arg:" _show_info_from_file "$arg" elif [ -d "$arg" ]; then arg="${arg%/}" [[ "." != "$arg" ]] && echo "${arg#./}/:" # Only print the 'header' if this function is not called from itself [ $recursive -eq 0 ] && echo ' === Files/Passwords [title username url] ===' _show_info_from_file "./${arg}/"* # Only print the 'header' if this function is not called from itself [ $recursive -eq 0 ] && echo ' === Directories/sites ===' for file in "${arg}/"*; do if [ -d "${file}" -a -x "${file}" ]; then if [ $recursive -eq 0 ]; then echo " ${file##*/}/" else # recursive ls -r "${file}" fi fi done fi done [ 0 -eq "$recursive" ] && echo } # }}} function show () { # {{{ local nb regex file answer local findopt='-maxdepth 1' [[ "-r" == "$1" ]] && { findopt= ; shift ; } regex=$1 nb=$(${zFIND} . $findopt -type f -regex '.*/[A-Za-z0-9@=_.+-]+' -print 2>/dev/null | ${zAWK} -v FS='/' '$NF ~ /'"${regex}"'/ { print $0 }' | ${zWC} -l) if [ 0 -eq $nb ]; then echo "No account match" return else # ask if we really want to display all the account if more than 5, unless FORCEYES is defined if [ -z "$FORCEYES" -a 5 -lt "$nb" ]; then echo -n "$nb results, Are you sure you want to proceed? (type yes) :" read answer case "$answer" in [Yy][Ee][Ss]) ;; [Nn][Oo]|[Nn]) echo Cancelled... return ;; *) echo "Please, be gentle..." echo Cancelled... return ;; esac fi echo '--------------------------------------' ${zFIND} . $findopt -type f -regex '.*/[A-Za-z0-9@=_.+-]+' -print 2>/dev/null | ${zAWK} -v FS='/' '$NF ~ /'"${regex}"'/ { print $0 }' | while read file ; do _checkfilename "${file##*/}" || continue echo "Title: ${file##*/}" ${zSED} -n ' 1{ /^Username: ./!berror p b } 2{ /^URL: ./!berror p b } 3{ /^Password: /!berror p b } 4{ /^Notes: /!berror p b } # quit after the fourth line 5q :error # on all other cases, the file is wrong a\ !!! incorrect password file !!! q ' "${file}" echo '--------------------------------------' done fi } # }}} function save () { # {{{ local lastMonth lastMonthLastBkp echo -n "Backup'ing..." ${zMKDIR} -p ~/pmBackup ${zCP} ${DB}.img ~/pmBackup/$(${zDATE} +%Y-%m-%d)-${USER}DB.img builtin cd ~/pmBackup lastMonth=$(${zDATE} -d 'last month' +'%Y-%m') lastMonthLastBkp=$(${zLS} -1t ${lastMonth}-[0-9][0-9]-${USER}DB.img 2>/dev/null | ${zHEAD} -n 1) [ ! -z $lastMonthLastBkp ] && ${zMOVE} -v -- $lastMonthLastBkp ${lastMonth}-${USER}DB.img ${zRM} -vf -- ${lastMonth}-[0-9][0-9]-${USER}DB.img echo "Done" builtin cd - &>/dev/null } # }}} function new () { # {{{ local title=$1 username url password notes # if $1 exist, then it's meant to be the title for the account, # otherwise we just ask for it interactively if [ ! -z "$title" ]; then if ! _checkfilename "$title"; then echo "These are the only characters allowed in the title: [A-Za-z0-9@=_.-]" echo "Action cancelled..." return 1 elif [ -f "$title" ]; then echo "this account already exists. Action cancelled..." return 1 fi # we need to lock the DB RW _setDB_rw || return 1 _my_prompt_command echo -e "\nTitle: $title" else # we need to lock the DB RW _setDB_rw || return 1 _my_prompt_command echo read -e -p "Title: " title _checkfilename "$title" || { echo "These are the only characters allowed in the title: [A-Za-z0-9@=_.-]"; _setDB_ro ; return 1 ; } [ -f "$title" ] && { echo "this account already exists. Action cancelled..."; _setDB_ro ; return 1 ; } fi # then for the URL, Password, and Notes fields: read -e -p "Username: " username [ -z "$username" ] && { echo "Can't be empty. Cancelling..."; _setDB_ro ; return 1 ; } read -e -p "URL: " url [ -z "$url" ] && { echo "Can't be empty. Cancelling..."; _setDB_ro ; return 1 ; } read -e -p "Password: " password read -e -p "Notes: " notes echo # creating the account: echo -e "Username: $username\nURL: $url\nPassword: $password\nNotes: $notes" > "$title" _setDB_ro show ^$title$ } # }}} function edit () { # {{{ # did I say I was using bash? ;) local field=() fieldW=() local title=0 username=1 url=2 password=3 notes=4 field[title]=$1 [ -z "${field[title]}" ] && { echo "You have to specify an account"; return 1 ; } if ! _file_ok "${field[title]}"; then echo "file '${field[title]}' doesn't exist in your CWD, _OR_ is incorrect. Action cancelled..." return 1 fi # file is correct, getting current field values for i in {1..4}; do field[$i]=$(${zSED} -rn "${i}s/^[^:]+: //p" ${field[title]}) done # we need to lock the DB RW now _setDB_rw || return 1 _my_prompt_command echo read -e -p "Title[${field[title]}]: " fieldW[title] if [ ! -z "${fieldW[title]}" -a "${fieldW[title]}" != "${field[title]}" ]; then _checkfilename "${fieldW[title]}" || { echo "These are the only characters allowed in the title: [A-Za-z0-9@=_.-]"; _setDB_ro ; return 1 ; } [ -f "${fieldW[title]}" ] && { echo "this account already exists. Action cancelled..."; _setDB_ro ; return 1 ; } ${zMOVE} "${field[title]}" "${fieldW[title]}" else fieldW[title]=${field[title]} fi read -e -p "Username[${field[username]}]: " fieldW[username] [ -z "${fieldW[username]}" ] && fieldW[username]=${field[username]} read -e -p "URL[${field[url]}]: " fieldW[url] [ -z "${fieldW[url]}" ] && fieldW[url]=${field[url]} read -e -p "Password[${field[password]}]: " fieldW[password] [ -z "${fieldW[password]}" ] && fieldW[password]=${field[password]} read -e -p "Notes[${field[notes]}]: " fieldW[notes] [ -z "${fieldW[notes]}" ] && fieldW[notes]=${field[notes]} echo echo -e "Username: ${fieldW[username]}\nURL: ${fieldW[url]}\nPassword: ${fieldW[password]}\nNotes: ${fieldW[notes]}" > "${fieldW[title]}" _setDB_ro show ^${fieldW[title]}$ } # }}} function changeURL () { # {{{ # checking args are correct if [ 1 -gt $# ];then echo "You have to specify at least one account name to modify..." return 1 fi for file in "$@"; do if ! _file_ok $file; then echo -e "$file: incorrect account...\nAction cancelled" return 1 fi done # collecting old/new values local oldURL newURL read -p "Enter the old URL (or IP) : " oldURL read -p "Enter the new URL (or IP) : " newURL echo _setDB_rw && for file in "$@"; do echo -n "$file : " # Do I really need to play with that file? if ${zGREP} -xq "URL: $oldURL" $file 2>/dev/null ; then # no : in a normal account, so this temp file should not be a problem ${zSED} 'q' $file > ./tmp:account echo "URL: $newURL" >> ./tmp:account ${zSED} -n '3{p;n;p;q}' $file >> ./tmp:account ${zMOVE} ./tmp:account $file echo "OK" else echo "URL (IP?) not found, skipping..." continue fi done echo _setDB_ro } # }}} function _account_completion () { # {{{ # I'm not really sure why complete -f edit, doesn't work the way I want, anyway, this will work at least :) # edit takes only one argument anyway [ "edit" == "${COMP_WORDS[0]}" -a 1 -lt "$COMP_CWORD" ] && return local titles=$(for file in *; do [ -f "$file" ] && echo "$file" ; done) # default COMP_WORDBREAKS is set to "'@><=;|&(: # this is the list of characters accepted in the title (=filename): A-Za-z0-9@=_.+- # be sure, completion won't break if there is a @ or a = in the title COMP_WORDBREAKS=${COMP_WORDBREAKS/@} COMP_WORDBREAKS=${COMP_WORDBREAKS/=} COMPREPLY=($(compgen -W "$titles" -- ${COMP_WORDS[COMP_CWORD]})) return 0 } # }}} function samexport () { # {{{ local type=$1 outCmd=${zCAT} case "$type" in csv) type=csv shift ;; html) type=html shift # if we're redirecting output to a file, then also print the headers.. # {{{ if [ ! -t 1 ]; then ${zCAT}< sampm: export "$@" EEOF fi # }}} outCmd="${zSED} -r s#^(.+),(.+),(.+),(.+),(.*)\$##;s/__C:o:M:a__/,/g" ;; *) # export type set to csv by default type=csv ;; esac for dir in "${@:-.}"; do [ -d "${dir}" ] || { echo $dir >> ~/tt ; echo "$dir : not a dir" >/dev/stderr ; continue; } cd "${dir}" FORCEYES=samOhYeah show -r cd - &>/dev/null done | ${zSED} -rn ' /^Title: /{ s/// s/,/__C:o:M:a__/g h n # Username /!!! incorrect password file !!!/b s/,/__C:o:M:a__/g s/^[^:]+: /,/ H n # URL /!!! incorrect password file !!!/b s/,/__C:o:M:a__/g s/^[^:]+: /,/ H n # Password /!!! incorrect password file !!!/b s/,/__C:o:M:a__/g s/^[^:]+: /,/ H n # Notes /!!! incorrect password file !!!/b s/,/__C:o:M:a__/g s/^[^:]+: /,/ H x s/\n//g p } ' | ${zSED} -r 's/^(.+),(.+),(.+),(.+),(.*)$/\1,\3,\2,\4,\5/' | ${zSORT} -t '@' -k 2 | ${outCmd} # if redirecting output to a file, also print the end of the document # {{{ if [ "html" == "${type}" -a ! -t 1 ]; then ${zCAT}<
TitleURLUsernamePasswordNotes
\1\2\3\4\5
EEOF fi # }}} } # }}} function showFriends () { # {{{ COLUMNS=150 ${zW} | ${zSED} -rn '\#/bin/bash[[:space:]]+--rcfile[[:space:]]+'"$HOME"'/.bashrc-sampm$#{ s/[[:space:]]+/ /g s/^[^ ]+ ([^ ]+) ([^ ]+) .*/\1 \2/ p }' | ${zAWK} '{ printf "%23s is connected on %s\n", $2, $1 }' } # }}} function checkDB () { # {{{ local VERBOSE= [[ "-vx" == "${1}x" ]] && VERBOSE=1 builtin shopt -s dotglob ${zFIND} . -type d -not -name 'lost+found' 2>/dev/null | while read dir; do if builtin cd "$dir"; then [ ! -z "$VERBOSE" ] && echo "$dir :" for file in *; do [ -f "$file" ] || continue _checkfilename "$file" || { echo "$dir/$file : incorrect filename"; continue ; } _file_ok "$file" || echo "$dir/$file : incorrect content" done builtin cd - >/dev/null fi done builtin shopt -u dotglob } # }}} complete -d rmdir complete -d cd complete -d samexport complete -F _account_completion edit complete -F _account_completion changeURL # to rename screen window via PS1 _windowName () { # {{{ echo -n ${LPWD##*/} } # }}} EOF # User specific settings/functions... case "$WHOAMI" in 'pmplayer') cat <<'EOF' >> "$1" # # You can create some aliases here, redefine some functions.. # function _getAccountNameFromPWD () { # {{{ # local site myPWD # [[ 1 -eq $# ]] && myPWD="$1" || myPWD="${LPWD}" # site=$(${zTR} '[:upper:]' '[:lower:]' <<< ${myPWD##*/}) # # # whatever # [[ "$-" != *i* ]] && echo -n $site || echo $site # } # # }}} # # Use the above function instead of the default one to set the name of screen window # alias _windowName=_getSiteNameFromPWD # # # complete the default help message # USER_SPECIFIC_HELP=" scd : cd helper (same use as in the svn support repository)" EOF ;; *) ;; esac cat <<'EOF' >> "$1" # Empty PATH to avoid mistake PATH= HISTFILE=~/.bash_history-sampm # We'll need these later MEFROM=$(${zWHO} -m | ${zAWK} '{ gsub(/[()]/,"",$5); print $2,$5 }') DB=${HOME}/${USER}DB # the following is automatically set when changing directory with cd, and when running the command pwd #LPWD=${PWD#${DB}} #LPWD=${LPWD#/} # make it easier to move between sites CDPATH="$HOME/${USER}DB" # we should be there cd "${DB}" # let's setup a nice prompt... PS1='\[\e[36m\]sampm:$LPWD >\[\e[0m\] ' # change screen window name, if screen is not 'local' [ "$TERM" == "screen" -a -z "$STY" ] && PS1="${PS1%?}"'\[\eksampm:$(_windowName)\e\\ \]' # just in case trap '_is_DB_rw && echo -e "\nSIGINT trapped, trying to remount the DB Read-Only" && _setDB_ro' SIGINT function _my_prompt_command () { # {{{ if ! _is_DB_rw ; then echo -e "[ \e[32mRead-Only DB\e[0m ]" return fi # DB is RW if [ -r ${DB}.lock -a ! -z "$MEFROM" ]; then local lock=$(<${DB}.lock) if [ ! -z "$lock" ]; then if [[ "$lock" == "$MEFROM" ]]; then echo -e "[ \e[31;1mRead-Write DB\e[0m: Don't forget to set it Read-Only ASAP with the \e[1m_setDB_ro\e[22m command ]" return else # check if the lock is still required (the guy is still logged in # local locker locker=$(COLUMNS=150 ${zW} -h | ${zSED} -rn '\#[^[:space:]]+[[:space:]]+'${lock/ /[[:space:]]+}'[[:space:]]+.*/bin/bash --rcfile '$HOME'/.bashrc-sampm#p') if [ -z "$locker" ]; then echo -e "The previous locker '\e[1m${lock#* }\e[22m' on '\e[1m${lock%% *}\e[22m' is no longer connected, and forgot to set back the DB Read-Only" echo -e "\e[32mYou may want to \e[32;01minsult him\e[0m" echo -n "Setting the DB Read-Only..." _setDB_ro --force && echo -e "OK\n[ \e[32mRead-Only DB\e[0m ]" else echo -e "[ \e[31;1mRead-Write DB \e[0mby '\e[1m${lock#* }\e[0m on '\e[1m${lock%% *}\e[0m' ]" fi return fi fi fi echo -e "[ \e[31;1mRead-Write DB: \e[0mBut no lock file, someone is either doing some administrative tasks or... nasty ones ]" } PROMPT_COMMAND=_my_prompt_command # }}} function help () { # {{{ ${zCAT}</dev/null WHOAMI=$user checkrc $RCFILE >/dev/null MD5SUM=$(md5sum "$RCFILE" 2>/dev/null) MD5SUM=${MD5SUM%% *} # replace with the new calculated md5 checksum of this conf file case "$user" in pmplayer|pmadmin) MD5SUM_LINE=$(echo MD5SUM_${user}_OK | tr '[[:lower:]]' '[[:upper:]]' ) ;; *) MD5SUM_LINE=MD5SUM_OK ;; esac #replacing the MD5SUM value in the script echo -n "old line: " sed -n "/^${MD5SUM_LINE}=/p" $PROGNAME echo -n "new line: " ed -s $PROGNAME <