head	1.14;
access;
symbols;
locks
	ids:1.14; strict;
comment	@# @;


1.14
date	2008.08.29.21.45.43;	author ids;	state Exp;
branches;
next	1.13;

1.13
date	2007.11.12.15.41.23;	author ids;	state Exp;
branches;
next	1.12;

1.12
date	2005.04.18.18.48.52;	author ids;	state Exp;
branches;
next	1.11;

1.11
date	2005.02.15.13.01.45;	author ids;	state Exp;
branches;
next	1.10;

1.10
date	2005.01.19.21.37.48;	author ids;	state Exp;
branches;
next	1.9;

1.9
date	98.07.31.14.37.26;	author ids;	state Exp;
branches;
next	1.8;

1.8
date	98.07.21.14.06.51;	author ids;	state Exp;
branches;
next	1.7;

1.7
date	98.03.17.12.55.26;	author ids;	state Exp;
branches;
next	1.6;

1.6
date	98.02.26.13.20.47;	author ids;	state Exp;
branches;
next	1.5;

1.5
date	96.12.05.14.58.13;	author ids;	state Exp;
branches;
next	1.4;

1.4
date	96.12.04.15.54.25;	author ids;	state Exp;
branches;
next	1.3;

1.3
date	95.10.16.12.50.22;	author ids;	state Exp;
branches;
next	1.2;

1.2
date	95.06.02.19.59.01;	author ids;	state Exp;
branches;
next	1.1;

1.1
date	95.06.01.20.54.43;	author ids;	state Exp;
branches;
next	;


desc
@@


1.14
log
@new time-style specification for "ls", achieving the traditional "Sep  6" format
 on the new DoC version of Ubuntu.
@
text
@#!/bin/sh -
#
#	append to regular incoming e-mail file, but "safely"
#	(with atomic link-locking etc).
#
progname=`basename $0`
ls_time_style="+%b %e  %Y
%b %e %H:%M"

if [ $# -lt 1 ]; then
	echo "usage: $progname <file>1+" >&2
	exit 1
fi

for arg in "$@@" ; do
	if [ ! \( -f "$arg" -a -r "$arg" \) ]; then
		echo "$arg not a readable regular file, exiting" >&2
		exit 1
	fi
done #for arg

date=`date`

echo -n "(moving...)"
mv $HOME/.email "$HOME/.email.$HOST.$$.$date"
if [ $? -ne 0 ]; then
	echo "" >&2
	echo "*** problem moving - giving up! ***" >&2
	exit 1
fi

#
#	sleep 2 to allow settling down of any incoming e-mail being added
#	to that inode. Then allow human judgement on the settling down,
#	since this criterion is not infallible!
#
reply="w"
while [ "x_$reply" = "x_w" ]; do
	echo -n "(settling...)"
	sleep 2
	echo "(seeking judgement...)"
	ls --time-style="$ls_time_style" -laFt $HOME | head --lines=15
	echo -n "Proceed - no or wait a bit or yes? [nwy] "
	read reply
done #while
if [ "x_$reply" != "x_y" ]; then
	echo "(exiting... do the rest manually!)" >&2
	exit 1
fi

echo -n "(appending $@@...)"
cat "$@@" >> "$HOME/.email.$HOST.$$.$date"
if [ $? -ne 0 ]; then
	echo "" >&2
	echo "*** problem appending $@@ - giving up! ***" >&2
	exit 1
fi

echo -n "(atomic linking...)"
perl -e "exit 1-link(q|$HOME/.email.$HOST.$$.$date|,q|$HOME/.email|)"
if [ $? -ne 0 ]; then
	echo "" >&2
	echo "******* IMPORTANT!!! *******" >&2
	echo "New mail has arrived. Atomic linking failed. Do the rest manually!" >&2
	exit 1
fi

echo -n "(unlinking...)"
rm -f "$HOME/.email.$HOST.$$.$date"
if [ $? -ne 0 ]; then
	echo "" >&2
	echo "*** problem unlinking - giving up! ***" >&2
	exit 1
fi

echo "(done!)"
echo "Final state:"
ls --time-style="$ls_time_style" -laFt $HOME | head --lines=15
@


1.13
log
@added time-style specification for "ls".
@
text
@d7 2
d42 1
a42 1
	ls --time-style=locale -laFt $HOME | head --lines=15
d78 1
a78 1
ls --time-style=locale -laFt $HOME | head --lines=15
@


1.12
log
@new syntax for head. (older syntax still works for now, but deprecated.)
@
text
@d40 1
a40 1
	ls -laFt $HOME | head --lines=15
d76 1
a76 1
ls -laFt $HOME | head --lines=15
@


1.11
log
@more thorough argument checking.
@
text
@d40 1
a40 1
	ls -laFt $HOME | head -15
d76 1
a76 1
ls -laFt $HOME | head -15
@


1.10
log
@MAJOR REVISION:
 * repair_mail -> appendmail:

> #     append to regular incoming e-mail file, but "safely"
> #     (with atomic link-locking etc).
@
text
@d13 7
@


1.9
log
@updated comments to reflect that both Linux and FreeBSD have the syndrome
 that the Bourne shell "cd" command doesn't cause exit on failure,
 but rather just barges on.
@
text
@d3 2
a4 1
#	repair_mail:
a5 16
#	attempt a repair operation on the receiving and/or updating of mail
#	(and its associated pop-state if relevant),
#	by moving the jammed-locked ~/.email[.poptmp] inodes
#	to one side and creating a fresh ~/.email[.poptmp]
#	(in a way that doesn't overwrite any instantly
#	newly-created ~/.email[.poptmp] that may now exist).
#
#	We keep the old inodes as a matter of goodwill, as explained by
#	Keith Sephton.
#


#
#	basic initialization
#
umask 077	#privacy of archive directory etc.
a6 4
potential_files_to_repair=".email .email.poptmp"
archive_dir="$HOME/.email.old-inodes"
archive_prefix="old-inode-"

d8 2
a9 5
#
#	some preliminary checks
#
if [ $# -ne 0 ]; then
	echo "$progname takes no arguments." >&2
d13 1
a13 6
files_to_repair=""	#initially
for potential_file_to_repair in $potential_files_to_repair ; do
	if [ -f $HOME/$potential_file_to_repair ]; then
		files_to_repair="$files_to_repair $potential_file_to_repair"
	fi
done #for potential_file_to_repair
d15 5
a19 2
if [ -z "$files_to_repair" ]; then
	echo "$progname: no mail state files to repair!" >&2
a22 2

mkdir -p $archive_dir
d24 15
a38 5
#	then still check it's a directory: mkdir -p doesn't complain if
#	it already existed as an ordinary file!
#
if [ ! -d $archive_dir ]; then
	echo "$progname: no archive directory for the jammed-locked inodes!" >&2
d42 2
a43 8
cd $archive_dir
#
#	Amazingly, on our Linux and FreeBSD machines, the Bourne shell
#	"cd" command doesn't cause exit on failure - it just barges on!
#	Naturally, all hell can break loose in a shell script which is
#	in a different directory from where it thinks it is.
#	So, to avoid such chaos, we check explicitly for failure here.
#
d45 2
a46 1
	echo "$progname: fatal error: cd $archive_dir failed." >&2
d50 8
d59 2
a60 4
#
#	critical region (two of this running at once would be a nightmare!)
#
tas .${progname}_busy
d62 2
a63 1
	echo "$progname: another run is busy." >&2
d67 3
a69 121

#
#	find a suitable filename to archive the old jammed-locked inode under.
#	(We assume if the archive contains no file of a given counter value
#	 with the *first* listed filename to archive as suffix, then it
#	 doesn't contain *any* files of that counter value. This is just to
#	 speed up the search.)
#
first_archive_suffix=`echo $files_to_repair | sed 's/[ 	].*$//'`

counter=1
digit_2=`expr $counter / 100`
digit_1=`expr \( $counter % 100 \) / 10`
digit_0=`expr $counter % 10`
counter_prefix="$archive_prefix$digit_2$digit_1$digit_0"
search_filename="$counter_prefix$first_archive_suffix"

while [ -f $search_filename ]; do
	counter=`expr $counter + 1`
	digit_2=`expr $counter / 100`
	digit_1=`expr \( $counter % 100 \) / 10`
	digit_0=`expr $counter % 10`
	counter_prefix="$archive_prefix$digit_2$digit_1$digit_0"
	search_filename="$counter_prefix$first_archive_suffix"
done #while


#
#	OK, now archive the old inodes!
#
for file_to_repair in $files_to_repair ; do
	mv $HOME/$file_to_repair $counter_prefix$file_to_repair
	if [ $? -ne 0 ]; then
		echo "$progname: fatal error moving $HOME/$file_to_repair to archive!" >&2
		rm -f .${progname}_busy
		exit 1
	fi
done #for file_to_repair


#
#	Create fresh inodes which will become the repaired files.
#
for file_to_repair in $files_to_repair ; do
	cp -p $counter_prefix$file_to_repair $counter_prefix$file_to_repair.COPY
	if [ $? -ne 0 ]; then
		echo "$progname: fatal error copying archived file $counter_prefix$file_to_repair to new inode!" >&2
		rm -f .${progname}_busy
		exit 1
	fi
done #for file_to_repair


#
#	Move the fresh inodes into place. However we don't literally move them.
#	Rather, we first atomically link each, then unlink its original name.
#	Otherwise, if any new mail has arrived (or new pop-state or whatever),
#	it would be non-atomically obliterated!
#
for file_to_repair in $files_to_repair ; do
	perl -e "exit 1-link(q|$counter_prefix$file_to_repair.COPY|,q|$HOME/$file_to_repair|)"
	if [ $? -ne 0 ]; then
		sed 's/^			//' << ________________here >&2
			******* IMPORTANT!!! *******

			New mail, or a new mail pop-state, has already arrived
			while the repair was in progress.
			You will have to manually fiddle around to merge the old and new mail states.

			A copy of the relevant old mail state is currently in
			$archive_dir/$counter_prefix$file_to_repair.COPY.
			Do not disturb the original inode, which is in
			$archive_dir/$counter_prefix$file_to_repair.
________________here

		rm -f .${progname}_busy
		exit 1
	fi
done #for file_to_repair


#
#	OK, the new inodes are in place: unlink their original names.
#
for file_to_repair in $files_to_repair ; do
	rm $counter_prefix$file_to_repair.COPY
	 #we don't use -f, as we are interested in its progress
	if [ $? -ne 0 ]; then
		sed 's/^			//' << ________________here >&2
			******* IMPORTANT!!! *******

			The newly-created $HOME/$file_to_repair cannot be unlinked with
			$archive_dir/$counter_prefix$file_to_repair.COPY.
			You will have to investigate this problem manually.

			Do not disturb the original inode, which is in
			$archive_dir/$counter_prefix$file_to_repair.
________________here

		rm -f .${progname}_busy
		exit 1
	fi
done #for file_to_repair


#
#	Let the user cast a skeptical eye over the state of the files
#	as they are now!
#
echo "$progname: repair completed!"
echo "Old inode(s):"
ls -lgaF `echo $files_to_repair | tr -s ' 	' '\012' | sed "s|^|$archive_dir/$counter_prefix|"`
echo "Repaired mail state (may include new incoming mail or new pop-state):"
ls -lgaF `echo $files_to_repair | tr -s ' 	' '\012' | sed "s|^|$HOME/|"`


#
#	Release critical region and finish.
#
rm -f .${progname}_busy
exit 0
@


1.8
log
@got rid of absolute pathname for perl (there's no reason it needs that
 special treatment, and it's hard work keeping up with all the changes and
 variations in its location on the different architectures!).
@
text
@d60 1
a60 1
#	Amazingly, on FreeBSD (or at least on fox), the Bourne shell
@


1.7
log
@added explicit exit status check on cd:

#
#       Amazingly, on FreeBSD (or at least on fox), the Bourne shell
#       "cd" command doesn't cause exit on failure - it just barges on!
#       Naturally, all hell can break loose in a shell script which is
#       in a different directory from where it thinks it is.
#       So, to avoid such chaos, we check explicitly for failure here.
#
@
text
@d141 1
a141 1
	/usr/local/bin/perl -e "exit 1-link(q|$counter_prefix$file_to_repair.COPY|,q|$HOME/$file_to_repair|)"
@


1.6
log
@changed mail file from ~/.mail to ~/.email (and associated stuff),
 now that staff accounts (or at least my account!) and student accounts
 are all using the new mailbox format and associated regime.
@
text
@d59 11
@


1.5
log
@more descriptive prefix for the old inodes
comment and control flow improvements.
@
text
@d7 2
a8 2
#	by moving the jammed-locked ~/.mail[.poptmp] inodes
#	to one side and creating a fresh ~/.mail[.poptmp]
d10 1
a10 1
#	newly-created ~/.mail[.poptmp] that may now exist).
d22 2
a23 2
potential_files_to_repair=".mail .mail.poptmp"
archive_dir="$HOME/.mail.old-inodes"
@


1.4
log
@MAJOR REVISION:
 * added repairing of ~/.mail.poptmp, as well as ~/.mail
 * more generic archive directory location, and create it if absent
 * check for which files potentially to be repaired actually exist
 * layout, comment and wording tidyups.
@
text
@d22 1
d24 1
a24 2
potential_files_to_repair=".mail .mail.poptmp"
archive_prefix="crap"
a34 10
mkdir -p $archive_dir
#
#	then still check it's a directory: mkdir -p doesn't complain if
#	it already existed as an ordinary file!
#
if [ ! -d $archive_dir ]; then
	echo "$progname: no archive directory for the jammed-locked inodes!" >&2
	exit 1
fi

d48 10
d94 1
a94 1
done
@


1.3
log
@added .mail suffix to the archived files.
@
text
@d3 1
a3 4
#	attempt a repair operation on the receiving and/or updating of mail,
#	by moving the jammed-locked ~/.mail inode to one side and creating
#	a fresh ~/.mail (in a way that doesn't overwrite any instantly
#	newly-created ~/.mail that may now exist).
d5 9
a13 1
#	We keep the old inode as a matter of goodwill, see Keith.
d20 1
d22 2
a23 1
archive_dir="$HOME/misc/systems_related/those_fabulous_locked_mail_files"
a24 1
archive_suffix=".mail"
d35 5
d45 13
d72 5
a76 1
#	find a suitable filename to archive the old jammed-locked inode under
d78 2
d84 2
a85 1
filename="$archive_prefix$digit_2$digit_1$digit_0$archive_suffix"
d87 1
a87 1
while [ -f $filename ]; do
d92 2
a93 1
	filename="$archive_prefix$digit_2$digit_1$digit_0$archive_suffix"
d98 1
a98 1
#	OK, now archive the old inode...
d100 8
a107 6
mv $HOME/.mail $filename
if [ $? -ne 0 ]; then
	echo "$progname: fatal error moving $HOME/.mail to archive!" >&2
	rm -f .${progname}_busy
	exit 1
fi
d111 1
a111 1
#	Create a fresh inode which will become the repaired mail.
d113 8
a120 6
cp -p $filename $filename.COPY
if [ $? -ne 0 ]; then
	echo "$progname: fatal error copying mail to new inode!" >&2
	rm -f .${progname}_busy
	exit 1
fi
d124 4
a127 4
#	Move it into place. However we don't literally move it.
#	Rather, we first atomically link it, then unlink its original name.
#	Otherwise, if any new mail has arrived, it would be
#	non-atomically obliterated!
d129 5
a133 4
/usr/local/bin/perl -e "exit 1-link(q|$filename.COPY|,q|$HOME/.mail|)"
if [ $? -ne 0 ]; then
	sed 's/^		//' << ________here >&2
		******* IMPORTANT!!! *******
d135 3
a137 2
		New mail has already arrived while the repair was in progress.
		You will have to manually fiddle around to merge the old and new mail.
d139 5
a143 5
		A copy of the old mail is currently in
		$archive_dir/$filename.COPY.
		Do not disturb the original inode, which is in
		$archive_dir/$filename.
________here
d145 4
a148 3
	rm -f .${progname}_busy
	exit 1
fi
d152 1
a152 1
#	OK, it's in place: unlink its original name.
d154 10
a163 4
rm $filename.COPY	#we don't use -f, as we are interested in its progress
if [ $? -ne 0 ]; then
	sed 's/^		//' << ________here >&2
		******* IMPORTANT!!! *******
d165 3
a167 7
		The newly-created $HOME/.mail cannot be unlinked with
		$archive_dir/$filename.COPY.
		You will have to investigate this problem manually.

		Do not disturb the original inode, which is in
		$archive_dir/$filename.
________here
d169 4
a172 3
	rm -f .${progname}_busy
	exit 1
fi
d180 4
a183 4
echo "Old inode:"
ls -lgaF $archive_dir/$filename
echo "Repaired mail (may include new incoming mail):"
ls -lgaF $HOME/.mail
@


1.2
log
@better name for critical region busy-file created by tas.
@
text
@d18 1
d54 1
a54 1
filename="$archive_prefix$digit_2$digit_1$digit_0"
d61 1
a61 1
	filename="$archive_prefix$digit_2$digit_1$digit_0"
@


1.1
log
@Initial revision

NOTE: here's the (somewhat anachronistic) README file of the archive directory:

> This directory is for keeping old jammed-locked
> ~/.email and ~/.email.poptmp files.
> (SEE STOP PRESS BELOW TOO!)
> 
> According to Keith, to remove them while the mailhost machine has still been
> continuously up will cause re-booting it to be somewhat more complicated
> when it eventually happens. Therefore, Keith says:
> "keep them until the mailhost machine has someday been re-booted". (!!!)
> 
> Logically (grumble grumble grumble), ordinary users should not have to concern
> themselves with such things. However, invoking (grumble grumble grumble)
> the concept of goodwill (grumble grumble grumble), I will, with clenched
> teeth, endeavour to resist temptation, and to archive the damned files here.
> 
> The actual contents are obsolete crap; furthermore the filenames have no
> significance and can be anything. However, keep away from manual creation of
> "old-inode-NNN.email[.poptmp]" style filenames,
> as this is done by my little script "repair_mail".
> 
>   Iain.
> 
> 
> STOP PRESS!---Apparently exactly the same jammed-locked state can occur
>               when saving to other ".[e]mail"-type files. I don't know if the
>               same re-booting business applies to them, but just in case,
>               I will (grumble grumble grumble) archive *those* damned files
>               here too! (At the moment I've usually chosen names that
>               give an obvious indication of what the original name was.)
> 
>                 Iain.
@
text
@d39 1
a39 1
tas .busy
d70 1
a70 1
	rm -f .busy
d81 1
a81 1
	rm -f .busy
d106 1
a106 1
	rm -f .busy
d127 1
a127 1
	rm -f .busy
d146 1
a146 1
rm -f .busy
@
