commit a4c584412c9dc16732c2201b3b2aeca88225c05f
parent 68834784349efbe0e38388d9415f2765283698e1
Author: Jaromil <jaromil@dyne.org>
Date:   Tue, 18 Sep 2012 21:58:32 +0200
tighter locking
Diffstat:
5 files changed, 74 insertions(+), 31 deletions(-)
diff --git a/src/jaro b/src/jaro
@@ -211,25 +211,54 @@ GNOMEKEY=0
 
 cleanexit() {
     func "Clean exit procedures"
-    # while ( ps ax | grep '[s]rm' > /dev/null
-    # 	test $? = 0 ); do sleep 1; done
 
-    # for f in `ls $TMPDIR/ | grep -v '.lock$'`; do
-    # 	{ test ! -r $TMPDIR/$f.lock } && { unlink $TMPDIR/$f }
-    # done
+    unset name login host protocol port password auth folders accountopt
+
+    # security check
+    { test "$TMPDIR" = "" } && {
+	error "Temporary directory not defined"
+	act "skipping cleanup, this might leave private traces."
+	return 1
+    }
+
+    # first delete dirs
+    for d in `find -O3 $TMPDIR/ -maxdepth 1 -type d`; do
+	{ test "$d" = "$TMPDIR/" } || { ${=rm} -r ${d} }
+    done
+
+    # then locks, with a warning
+    for l in `find -O3 $TMPDIR/ -maxdepth 1 -type f -name '*.lock'`; do
+	lname=`basename ${(s:.lock:)l}`
+
+	# skip if in course of unlink - parallel operation, see unlink()
+	{ test -r ${TMPDIR}/${lname}.unlink } && { continue }
+
+	pid="$lname.pid"
+	if [ -r ${pid} ]; then
+	    error "forced removal of lock created by pid $pid: $lname"
+	    rm -f ${TMPDIR}/${pid}
+	else
+	    error "forced removal of lock created by unknown pid: $lname"
+	fi
+	rm -f ${TMPDIR}/${lock}
+
+	# remove the actual file
+	if [ -r ${TMPDIR}/$lname ]; then ${=rm} ${TMPDIR}/$lname
+	else error "stale lock: locked file not found"; fi
+
+    done
+
 
 #    { test $TMPRAM = 1 } && { rmdir $TMPDIR }
-    unset typeset -h name login host protocol port password auth folders accountopt
 }
 # make sure tmp is wiped from sensitive data in case of sigINT
 TRAPINT() {
 	error "Caught signal, aborting operations."
-	{ test $CLEANEXIT = 1 } && { cleanexit }
-	error "Forced removal of locks"
-	{ test $TMPDIR } && {
-	    for l in `find $TMPDIR/`; do
-		${=rm} $l; done
-	}
+
+	{ test $CLEANEXIT = 1 } && {
+	    error "Forced removal of locks"
+	    cleanexit }
+
 	if [ "$DEBUG" = "1" ]; then return 1
 	else exit 1; fi
 }
@@ -294,7 +323,7 @@ option_value() {
 
 
 usage() {
-    cat <<EOF
+    cat <<EOF | more
 Jaro Mail $VERSION - your humble and faithful electronic postman
 
  Copyright (C) 2010-2012 by Jaromil @ Dyne.org, License GNU GPL v3+
@@ -317,7 +346,7 @@ Options:
 
  -h     print this help
  -v     version information for this tool
- -q     run quietly without printing informations
+ -q     run quietly without printing information
  -n     dry run, show operations without executing them
  -D     print debugging information at runtime
 
@@ -355,7 +384,7 @@ Please report bugs on <http://bugs.dyne.org>.
 EOF
 }
 
-# TODO: For more informations on Jaro Mail read the manual: man jaro
+# TODO: For more information on Jaro Mail read the manual: man jaro
 typeset -A subcommands_opts
 
 main()
@@ -380,6 +409,8 @@ main()
     subcommands_opts[peek]="R -readonly=R"
     subcommands_opts[open]="R -readonly=R"
 
+    subcommands_opts[help]=""
+
     subcommands_opts[update]=""
 
     subcommands_opts[stat]=""
@@ -508,6 +539,8 @@ main()
 
 	update)  update ;;
 
+	help) CLEANEXIT=0; usage ;;
+
 	search)  CLEANEXIT=0; search ${PARAM} ;;
 
 	stat)   CLEANEXIT=0; stats ${PARAM} ;;
diff --git a/src/zlibs/email b/src/zlibs/email
@@ -82,6 +82,7 @@ fetchall() {
     done
     return $res
 }
+
 fetch() {
     { test "$account" = "" } && {
 	fetchall; return $? }
@@ -267,8 +268,8 @@ EOF
 		act "Mail sent succesfully"
 	   # whitelist those to whom we send mails
 		cat ${mail} | $WORKDIR/bin/jaro -q learn recipient
-		${=rm} ${mail} &
-		unlink ${smtp} &
+		${=rm} ${mail}
+		unlink ${smtp}
 	    fi
 	done
 	unlink $tmp
diff --git a/src/zlibs/filters b/src/zlibs/filters
@@ -116,8 +116,9 @@ EOF
     #######
     # SIEVE
     act "generating sieve filters"
-    id=$RANDOM
+    id=$datestamp.$RANDOM
     sieve=$WORKDIR/sieve.filter
+    lock $sieve
     rm -f $sieve
     touch $sieve
     chmod 600 $sieve
@@ -319,6 +320,7 @@ if header :is "X-Spam-Flag" "YES" {
 
 EOF
 
+unlock $sieve
 
 #### PROCMAIL
 
diff --git a/src/zlibs/locking b/src/zlibs/locking
@@ -35,21 +35,31 @@ lock() {
 	    return 0 ;;
     esac
 }
+
 newlock() { # create locked
     func "creating locked file: $1"
     touch $1
     chmod 600 $1
     lock $1
 }
-unlock() {
-    func "unlock: $1"
+
+pidcheck() { # check if lock belongs to us
     lockpid="`cat ${1}.pid`"
     { test -r "${1}.pid" } && {
 	{ test "$$" != "$lockpid" } && {
-	    error "Unlock attempt by different PID: $1"
-	    error "Created by $lockpid now $$ is trying to unlock"
+	    error "Unlock attempt by different PID on `basename $1`"
+	    act "created by $lockpid now we ($$) try to unlock"
+	    act "skipped removal: $1"
 	    return 1 }
     }
+    return 0
+}
+
+unlock() {
+    func "unlock: $1"
+
+    pidcheck $1
+    { test $? = 0 } || { return 1 }
 
     $WORKDIR/bin/dotlock -u ${=@}
     { test $? != 0 } && { error "Unable to unlock: $1"; return 1 }
@@ -59,22 +69,19 @@ unlock() {
 unlink() { # delete a file that we are locking
     func "unlink: $1"
     # use with care! this can permanently erase currently locked files
-    # only the locking PID should use it on its own locks
 
-    { test -r "${1}.pid" } && {
-	lockpid="`cat ${1}.pid`"
-	{ test "$$" != "$lockpid" } && {
-	    error "Unlock attempt by different PID: $1"
-	    error "Created by $lockpid now $$ is trying to unlock"
-	    return 1 }
-    }
+    pidcheck $1
+    { test $? = 0 } || { return 1 }
 
+    # signal that is unlinking (for parallel operation)
+    touch ${1}.unlink
     (
 	${=rm} ${1}
 	touch ${1}
 	$WORKDIR/bin/dotlock -d -f ${1}
 	{ test $? != 0 } && { error "Unable to unlink: $1"; return 1 }
 	{ test -r "${1}.pid" } && { rm -f ${1}.pid }
+	rm -f ${1}.unlink
     ) &!
     return 0
 }
diff --git a/src/zlibs/search b/src/zlibs/search
@@ -123,7 +123,7 @@ EOF
     } # DRYRUN
     ${=rm} $TMPDIR/search.db.$id
     ${=rm} $TMPDIR/search.conf.$id
-    ${=rm} $TMPDIR/search.result.$id
+    ${=rm} -r $TMPDIR/search.result.$id
     return $exitcode
 }