#!/bin/bash
# Author: Alex Efros <powerman-asdf@yandex.ru>, 2003
# License: Public Domain
#
# exfile: Manage exclusive access to files.
#
# Current file state (is it opened, who open it and when) maintained in
# special subdirectory .ex in directory with files. Example:
#   $ echo test > file
#   $ exfile open user1 file
#   $ exfile read user1 file
#   test
#   $ exfile open user2 file
#   Can't open 'file': opened by 'user1' at 'Thu Apr  3 20:07:40 EEST 2008'
#   $ exfile read user2 file
#   Can't read 'file': opened by 'user1' at 'Thu Apr  3 20:07:40 EEST 2008'
#   $ echo test2 | exfile write user1 file
#   $ exfile read user1 file
#   test2
#   $ exfile close user1 file
#   $ exfile close user1 file
#   'file': not opened

VERSION="2.00"

export CMD=$1 
export ID=$2
export FILE=$3


if [ "$CMD" == "" -o "$CMD" == "-h" -o "$CMD" == "--help" ]; then
    cat <<USAGE
Usage: `basename $0` command id filename
    filename should be in current dir
    available commands
	 open : gain exclusive file access  (file may not exists)
	 read : copy file  to stdout	    (file should be opened)
	write : copy stdin to file	    (file should be opened)
	close : drop exclusive file access  (file should be opened)
    exit codes
	0 : no error
	2 : file not opened (read,write,close)
	3 : file opened by another id (open,read,write,close)
	X : unknown error
USAGE
    exit 1
fi
if [ "$ID" == "" ]; then
    echo "error: id required"
    exit 1
fi
if [ "$FILE" == "" ]; then
    echo "error: filename required"
    exit 1
fi
if echo "$FILE" | grep -q /; then
    echo "error: filename should be in current dir"
    exit 1
fi

    
export EXITCODE="/tmp/excode.$$"
echo 0 >"$EXITCODE"
mkdir .ex >/dev/null 2>&1
setlock ".ex/$FILE" bash 4<&0 <<'EOCMD'


if [ ! -s ".ex/$FILE" ]; then
    if [ "$CMD" == "open" ]; then
	echo "$ID" >".ex/$FILE"
	exit
    fi
    echo "'$FILE': not opened" >&2
    echo 2 >"$EXITCODE"; exit
fi
EXID=`cat ".ex/$FILE" 2>/dev/null`;
EXDATE=`date -r ".ex/$FILE" 2>/dev/null`;
if [ "$EXID" != "$ID" ]; then
    echo "Can't $CMD '$FILE': opened by '$EXID' at '$EXDATE'" >&2
    echo 3 >"$EXITCODE"; exit
fi
if   [ "$CMD" == "open"  ]; then
    echo "'$FILE': already opened" >&2
elif [ "$CMD" == "close" ]; then
    echo -n >".ex/$FILE"
elif [ "$CMD" == "read"  ]; then
    cat "$FILE" 
elif [ "$CMD" == "write" ]; then
    cat >"/tmp/exfile.$$" <&4
    mv -f "/tmp/exfile.$$" "$FILE"
else
    echo "Unknown command: $CMD" >&2
    echo 1 >"$EXITCODE"; exit
fi
exit 0
EOCMD


EXIT1=$?
EXIT2=`cat "$EXITCODE"`
rm -f "$EXITCODE"
[ "$EXIT1" == "0" ] || exit "$EXIT1"
exit "$EXIT2"

