phil@sequent.UUCP (Phil Hochstetler) (01/20/89)
I got so many requests of this code that I decided to just go ahead and post it. Here are the mods to run with 4.3 BSD style flock with elm 2.1PL1. (BTW: This is required to run elm 2.1 on our DYNIX 3.0 BSD based OS). This "diff -c" script when run into patch will upgrade your elm 2.1 PL1 version to automatically use flock() style mail locking. Apply this patch in the usual way, via cd'ing to the top level directory and running "patch -p1" with this file as standard input. In other words, do: > patch.flock (write this file to "patch.flock") cd src/elm2.1PL1 (or whatever you call your source) patch -p1 < patch.flock These patches fix: o Adding support for flock() in Configure and in the source code. o Fixes the BSD botch which turned off CRMOD (fix posted to net previously) o Replaces reference in Configure to "dirname" (AT&T only utility) o Adds portable support for parallel make (Sequent machines only, but won't hurt other machines) I have noted that 2.1 PL1 release is a rough release. It doesn't stand a chance of passing lint. I noted several problems with the code that may result in trashed mailboxes. One thing that bothers me is that the code to unlock a mailbox get called from many places and frequently when a lock has not been asserted. The code I added is bullet proof in this regard. The downside of this is that elm may blow away a lock (or lockfile) when doing simple things like changing a folder file (not related to $MAIL). Sigh. Anyway, I have not had a problem with this flock version in a month of use. diff -rc elm2.1PL1.orig/Configure elm2.1PL1/Configure *** elm2.1PL1.orig/Configure Thu Jan 19 15:04:52 1989 --- elm2.1PL1/Configure Thu Jan 19 15:02:57 1989 *************** *** 828,833 ;; esac osdefine="" large="" cflags="" --- 828,834 ----- ;; esac + lkdefine="" osdefine="" large="" cflags="" *************** *** 856,861 if [ "$sequent" != 1 ] ; then getopt="" fi ;; PYRAMID) osdefine="-DBSD -DNO_VAR_ARGS" --- 857,870 ----- if [ "$sequent" != 1 ] ; then getopt="" fi + result="`strings -a /bin/mail | grep '^\.lock'`" + if [ "$result" = "" ] ; then + echo "You appear to use flock for mail delivery. Good!" + lkdefine="-DFLOCK" + else + echo "You appear to use /usr/spool/mail/\$USER.lock for mail delivery." + lkdefine="" + fi ;; PYRAMID) osdefine="-DBSD -DNO_VAR_ARGS" *************** *** 871,876 if [ "$use_dbm" = 1 ] ; then libs="$libs -ldbm" fi echo "s^>os-define<^$osdefine^" >> $SED2 echo "s^>large<^$large^" >> $SED2 echo "s^>cflags<^$cflags^" >> $SED2 --- 880,886 ----- if [ "$use_dbm" = 1 ] ; then libs="$libs -ldbm" fi + echo "s^>lk-define<^$lkdefine^" >> $SED2 echo "s^>os-define<^$osdefine^" >> $SED2 echo "s^>large<^$large^" >> $SED2 echo "s^>cflags<^$cflags^" >> $SED2 *************** *** 1051,1057 # phew! ! troffdir=`dirname $troff` if [ -f "$troffdir/tbl" ] then --- 1061,1069 ----- # phew! ! troffdir="`expr ${troff-.}'/' : '\(/\)[^/]*/$' \ ! \| ${troff-.}'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \ ! \| .`" if [ -f "$troffdir/tbl" ] then diff -rc elm2.1PL1.orig/Makefile.mt elm2.1PL1/Makefile.mt *** elm2.1PL1.orig/Makefile.mt Thu Jan 19 15:04:54 1989 --- elm2.1PL1/Makefile.mt Thu Jan 19 14:39:55 1989 *************** *** 6,11 # (C) Copyright 1986, 1987, by Dave Taylor # # $Log: Makefile.mt,v $ # Revision 2.1 88/09/15 19:55:01 syd # Initial 2.1 Release # --- 6,17 ----- # (C) Copyright 1986, 1987, by Dave Taylor # # $Log: Makefile.mt,v $ + # Revision 1.2 89/01/19 13:44:21 phil + # Added define for FLOCK mods. + # + # Revision 1.1 88/12/19 09:14:20 phil + # Initial revision + # # Revision 2.1 88/09/15 19:55:01 syd # Initial 2.1 Release # *************** *** 42,48 CATMAN= /usr/local/man/cat1 SHAR= /usr/local/bin/shar -s 60000 ! DEFINE = >os-define< LIB2 = >lib2< ######################### --- 48,54 ----- CATMAN= /usr/local/man/cat1 SHAR= /usr/local/bin/shar -s 60000 ! DEFINE = >os-define< >lk-define< LIB2 = >lib2< ######################### diff -rc elm2.1PL1.orig/filter/Makefile.mt elm2.1PL1/filter/Makefile.mt *** elm2.1PL1.orig/filter/Makefile.mt Thu Jan 19 15:05:27 1989 --- elm2.1PL1/filter/Makefile.mt Thu Jan 19 13:31:27 1989 *************** *** 5,10 # (C) Copyright 1986, Dave Taylor # # $Log: Makefile.mt,v $ # Revision 2.1 88/09/15 21:26:44 syd # Initial 2.1 Release # --- 5,16 ----- # (C) Copyright 1986, Dave Taylor # # $Log: Makefile.mt,v $ + # Revision 1.2 89/01/19 13:31:13 phil + # Added $& for parallel make. + # + # Revision 1.1 88/12/19 09:15:29 phil + # Initial revision + # # Revision 2.1 88/09/15 21:26:44 syd # Initial 2.1 Release # *************** *** 33,39 all: ${OBJ} ! ../bin/filter : ${HDRS} ${BINARIES} ${CC} ${CFLAGS} ${DEFINE} ${BINARIES} -o ${OBJ} buffer.o : ${HDRS} buffer.c --- 39,45 ----- all: ${OBJ} ! ../bin/filter : ${HDRS} $& ${BINARIES} ${CC} ${CFLAGS} ${DEFINE} ${BINARIES} -o ${OBJ} buffer.o : ${HDRS} buffer.c diff -rc elm2.1PL1.orig/src/Makefile.mt elm2.1PL1/src/Makefile.mt *** elm2.1PL1.orig/src/Makefile.mt Thu Jan 19 15:05:54 1989 --- elm2.1PL1/src/Makefile.mt Thu Jan 19 13:42:45 1989 *************** *** 5,10 # (C) Copyright 1986, 1987, Dave Taylor # # $Log: Makefile.mt,v $ # Revision 2.1 88/09/15 20:07:11 syd # Initial 2.1 Release # --- 5,16 ----- # (C) Copyright 1986, 1987, Dave Taylor # # $Log: Makefile.mt,v $ + # Revision 1.2 89/01/19 13:42:23 phil + # Added parallel make mods and an extra define for FLOCK code. + # + # Revision 1.1 88/12/19 09:16:26 phil + # Initial revision + # # Revision 2.1 88/09/15 20:07:11 syd # Initial 2.1 Release # *************** *** 16,22 SHELL=/bin/sh ! DEFINE= -DDEBUG >os-define< LIB2 = >lib2< # IF you're on an ACSnet system (Australia) then --- 22,28 ----- SHELL=/bin/sh ! DEFINE= -DDEBUG >os-define< >lk-define< LIB2 = >lib2< # IF you're on an ACSnet system (Australia) then *************** *** 60,66 CC= >cc< RM= >rm< ! ../bin/elm: ${OBJS} ${EXTRA} ${HEADERS} ../hdrs/elm.h ${CC} ${LFLAGS} -o ${BIN}/elm -n ${OBJS} ${LIBS} ${LIB2} .c.o: ${HEADERS} --- 66,72 ----- CC= >cc< RM= >rm< ! ../bin/elm: $& ${OBJS} ${EXTRA} ${HEADERS} ../hdrs/elm.h ${CC} ${LFLAGS} -o ${BIN}/elm -n ${OBJS} ${LIBS} ${LIB2} .c.o: ${HEADERS} diff -rc elm2.1PL1.orig/src/curses.c elm2.1PL1/src/curses.c *** elm2.1PL1.orig/src/curses.c Thu Jan 19 15:06:07 1989 --- elm2.1PL1/src/curses.c Thu Jan 19 13:39:40 1989 *************** *** 2,8 static char rcsid[] = "@(#)$Id: curses.c,v 2.1.1.2 88/09/23 syd Exp $"; /******************************************************************************* ! * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ * * Copyright (c) 1986 Dave Taylor ******************************************************************************* --- 2,8 ----- static char rcsid[] = "@(#)$Id: curses.c,v 2.1.1.2 88/09/23 syd Exp $"; /******************************************************************************* ! * The Elm Mail System - $Revision: 1.2 $ $State: Exp $ * * Copyright (c) 1986 Dave Taylor ******************************************************************************* *************** *** 13,18 * ******************************************************************************* * $Log: curses.c,v $ * Revision 2.1 88/09/15 20:27:44 syd * checked in with -k by syd at 88.09.15.20.27.44. * --- 13,24 ----- * ******************************************************************************* * $Log: curses.c,v $ + * Revision 1.2 89/01/19 13:39:17 phil + * Fix flags for BSD case so CRMOD does not get turned off. + * + * Revision 1.1 88/12/19 09:43:00 phil + * Initial revision + * * Revision 2.1 88/09/15 20:27:44 syd * checked in with -k by syd at 88.09.15.20.27.44. * *************** *** 785,791 (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/ #ifdef BSD ! _raw_tty.sg_flags &= ~(ECHO | CRMOD); /* echo off */ _raw_tty.sg_flags |= CBREAK; /* raw on */ #else _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode */ --- 791,797 ----- (void) ioctl(TTYIN, TCGETA, &_raw_tty); /** again! **/ #ifdef BSD ! _raw_tty.sg_flags &= ~ECHO; /* echo off */ _raw_tty.sg_flags |= CBREAK; /* raw on */ #else _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode */ diff -rc elm2.1PL1.orig/src/leavembox.c elm2.1PL1/src/leavembox.c *** elm2.1PL1.orig/src/leavembox.c Thu Jan 19 15:06:39 1989 --- elm2.1PL1/src/leavembox.c Thu Jan 19 13:40:16 1989 *************** *** 2,8 static char rcsid[] = "@(#)$Id: leavembox.c,v 2.2 88/09/15 20:28:45 syd Exp $"; /******************************************************************************* ! * The Elm Mail System - $Revision: 2.2 $ $State: Exp $ * * Copyright (c) 1986 Dave Taylor ******************************************************************************* --- 2,8 ----- static char rcsid[] = "@(#)$Id: leavembox.c,v 2.2 88/09/15 20:28:45 syd Exp $"; /******************************************************************************* ! * The Elm Mail System - $Revision: 1.2 $ $State: Exp $ * * Copyright (c) 1986 Dave Taylor ******************************************************************************* *************** *** 13,18 * ******************************************************************************* * $Log: leavembox.c,v $ * Revision 2.2 88/09/15 20:28:45 syd * checked in with -k by syd at 88.09.15.20.28.45. * --- 13,24 ----- * ******************************************************************************* * $Log: leavembox.c,v $ + * Revision 1.2 89/01/19 13:39:57 phil + * Added 4.3 style FLOCK mods for interacting with mailer. + * + * Revision 1.1 88/12/19 08:44:37 phil + * Initial revision + * * Revision 2.2 88/09/15 20:28:45 syd * checked in with -k by syd at 88.09.15.20.28.45. * *************** *** 318,323 } if (infile != NULL) unlink(infile); /* and BLAMO! */ --- 324,330 ----- } + #ifndef FLOCK if (infile != NULL) unlink(infile); /* and BLAMO! */ #endif !FLOCK *************** *** 320,325 if (infile != NULL) unlink(infile); /* and BLAMO! */ if (to_save && (mbox_specified || pending)) { if (link(outfile, infile) != 0) --- 327,333 ----- #ifndef FLOCK if (infile != NULL) unlink(infile); /* and BLAMO! */ + #endif !FLOCK if (to_save && (mbox_specified || pending)) { #ifdef FLOCK *************** *** 322,327 unlink(infile); /* and BLAMO! */ if (to_save && (mbox_specified || pending)) { if (link(outfile, infile) != 0) if (errno == EXDEV || errno == EEXIST ) { /** different file devices! Use copy! **/ --- 330,339 ----- #endif !FLOCK if (to_save && (mbox_specified || pending)) { + #ifdef FLOCK + if (1) + if (1) { + #else if (link(outfile, infile) != 0) if (errno == EXDEV || errno == EEXIST ) { /** different file devices! Use copy! **/ *************** *** 325,330 if (link(outfile, infile) != 0) if (errno == EXDEV || errno == EEXIST ) { /** different file devices! Use copy! **/ if (copy(outfile, infile) != 0) { dprint(1, (debugfile, "leavembox: copy(%s, %s) failed;", outfile, infile)); --- 337,343 ----- if (link(outfile, infile) != 0) if (errno == EXDEV || errno == EEXIST ) { /** different file devices! Use copy! **/ + #endif FLOCK if (copy(outfile, infile) != 0) { dprint(1, (debugfile, "leavembox: copy(%s, %s) failed;", outfile, infile)); *************** *** 403,410 error_name(errno), infile); } - unlock(); /* remove the lock on the file ASAP! */ - /** finally, let's change the ownership of the default outgoing mailbox, if needed **/ --- 416,421 ----- error_name(errno), infile); } /** finally, let's change the ownership of the default outgoing mailbox, if needed **/ *************** *** 411,417 if (to_save) chown(outfile, userid, groupid); } - mailfile_size = bytes(infile); return(to_delete); } --- 422,427 ----- if (to_save) chown(outfile, userid, groupid); } mailfile_size = bytes(infile); unlock(); return(to_delete); *************** *** 413,418 } mailfile_size = bytes(infile); return(to_delete); } --- 423,429 ----- chown(outfile, userid, groupid); } mailfile_size = bytes(infile); + unlock(); return(to_delete); } *************** *** 418,423 char lock_name[SLEN]; int we_created_lock = 0; /* set to true iff we create it */ lock(direction) int direction; --- 429,437 ----- char lock_name[SLEN]; int we_created_lock = 0; /* set to true iff we create it */ + #ifdef FLOCK + static int flock_fd = -1; + #endif FLOCK lock(direction) int direction; *************** *** 422,427 lock(direction) int direction; { /** Create lock file to ensure that we don't get any mail while altering the mailbox contents! If it already exists sit and spin until --- 436,488 ----- lock(direction) int direction; { + #ifdef FLOCK + register int iteration = 0; + + do { + if (flock_fd == -1 && (flock_fd = open(infile, O_RDONLY)) < 0) { + error("Can't open mailfile in lock().\n"); + leave(); + } + if (flock(flock_fd, LOCK_NB|LOCK_EX) >= 0) + return; /* success */ + if (errno != EWOULDBLOCK) { + error("Can't flock mailfile\n"); + leave(); + } + dprint(2, (debugfile, "Mail file is locked! Waiting...(lock)\n")); + if (direction == INCOMING) { + if (iteration == 0) + PutLine0(LINES, 0, "Mail being received...\t\twaiting...1 "); + else + printf("%d ", iteration); + fflush(stdout); + } + else + error1(" Attempt #%d: Mail being received...waiting ", iteration); + sleep(5); + } while (iteration++ < MAX_ATTEMPTS); + + /* Okay...we die and leave, not updating the mailfile mbox or + any of those! */ + + if (direction == INCOMING) { + PutLine1(LINES, 0, "\n\r\n\rGiving up after %d iterations...\n\r", + iteration); + PutLine0(LINES, 0, + "\n\rPlease try to read your mail again in a few minutes.\n\r\n\r"); + dprint(1, (debugfile, + "Warning: bailing out after %d iterations...(lock)\n", + iteration)); + leave_locked(0); + } + else { + dprint(1, (debugfile, + "Warning: after %d iterations, timed out! (lock)\n", + iteration)); + leave(error("Timed out on lock file reads. Leaving program.")); + } + #else /** Create lock file to ensure that we don't get any mail while altering the mailbox contents! If it already exists sit and spin until *************** *** 548,553 /* if we get here we've created the lock file, so lets just split */ close(lock_fd); /* close it. We don't want to KEEP the thing! */ } unlock() --- 609,615 ----- /* if we get here we've created the lock file, so lets just split */ close(lock_fd); /* close it. We don't want to KEEP the thing! */ + #endif FLOCK } unlock() *************** *** 556,560 processing routine to ensure that the lock file is NEVER left sitting in the mailhome directory! **/ (void) unlink(lock_name); } --- 618,630 ----- processing routine to ensure that the lock file is NEVER left sitting in the mailhome directory! **/ + #ifdef FLOCK + if (flock_fd != -1) { + (void) flock(flock_fd, LOCK_UN); + (void) close(flock_fd); + flock_fd = -1; + } + #else (void) unlink(lock_name); #endif } *************** *** 557,560 left sitting in the mailhome directory! **/ (void) unlink(lock_name); } --- 626,630 ----- } #else (void) unlink(lock_name); + #endif } diff -rc elm2.1PL1.orig/src/utils.c elm2.1PL1/src/utils.c *** elm2.1PL1.orig/src/utils.c Thu Jan 19 15:07:22 1989 --- elm2.1PL1/src/utils.c Thu Jan 19 13:42:03 1989 *************** *** 2,8 static char rcsid[] = "@(#)$Id: utils.c,v 2.2 88/09/15 20:30:04 syd Exp $"; /******************************************************************************* ! * The Elm Mail System - $Revision: 2.2 $ $State: Exp $ * * Copyright (c) 1985 Dave Taylor ******************************************************************************* --- 2,8 ----- static char rcsid[] = "@(#)$Id: utils.c,v 2.2 88/09/15 20:30:04 syd Exp $"; /******************************************************************************* ! * The Elm Mail System - $Revision: 1.2 $ $State: Exp $ * * Copyright (c) 1985 Dave Taylor ******************************************************************************* *************** *** 13,18 * ******************************************************************************* * $Log: utils.c,v $ * Revision 2.2 88/09/15 20:30:04 syd * checked in with -k by syd at 88.09.15.20.30.04. * --- 13,24 ----- * ******************************************************************************* * $Log: utils.c,v $ + * Revision 1.2 89/01/19 13:41:26 phil + * Added ifdef for FLOCK code so unlink is not done if FLOCK defined. + * + * Revision 1.1 88/12/29 13:40:52 phil + * Initial revision + * * Revision 2.2 88/09/15 20:30:04 syd * checked in with -k by syd at 88.09.15.20.30.04. * *************** *** 232,237 sprintf(buffer,"%s/%s", home, readmsg_file); /* readmsg temp */ (void) unlink(buffer); sys_lock_file(buffer, username); /* lock file */ (void) unlink(buffer); --- 238,244 ----- sprintf(buffer,"%s/%s", home, readmsg_file); /* readmsg temp */ (void) unlink(buffer); + #ifndef FLOCK sys_lock_file(buffer, username); /* lock file */ (void) unlink(buffer); #endif !FLOCK *************** *** 234,239 sys_lock_file(buffer, username); /* lock file */ (void) unlink(buffer); if (! mail_only) { MoveCursor(LINES,0); --- 241,247 ----- #ifndef FLOCK sys_lock_file(buffer, username); /* lock file */ (void) unlink(buffer); + #endif !FLOCK if (! mail_only) { MoveCursor(LINES,0); diff -rc elm2.1PL1.orig/utils/Makefile.mt elm2.1PL1/utils/Makefile.mt *** elm2.1PL1.orig/utils/Makefile.mt Thu Jan 19 15:07:27 1989 --- elm2.1PL1/utils/Makefile.mt Thu Jan 19 13:43:30 1989 *************** *** 5,10 # (C) Copyright 1986, 1987 Dave Taylor # # $Log: Makefile.mt,v $ # Revision 2.1 88/09/15 21:08:39 syd # Initial 2.1 Release # --- 5,16 ----- # (C) Copyright 1986, 1987 Dave Taylor # # $Log: Makefile.mt,v $ + # Revision 1.2 89/01/19 13:43:07 phil + # Added getopt.c line to building of newmail. + # + # Revision 1.1 88/12/19 09:17:19 phil + # Initial revision + # # Revision 2.1 88/09/15 21:08:39 syd # Initial 2.1 Release # *************** *** 45,52 ${CC} ${CFLAGS} ${DEFINE} from.c ../src/opt_utils.o \ ../src/string2.o >getopt< expand.o -o ../bin/frm ! ../bin/newmail: ../src/opt_utils.c newmail.c ../src/string2.o expand.o ! ${CC} ${CFLAGS} ${DEFINE} newmail.c expand.o \ ../src/string2.o -o ../bin/newmail ../bin/listalias: listalias.c --- 51,58 ----- ${CC} ${CFLAGS} ${DEFINE} from.c ../src/opt_utils.o \ ../src/string2.o >getopt< expand.o -o ../bin/frm ! ../bin/newmail: ../src/opt_utils.c newmail.c ../src/string2.o expand.o getopt.c ! ${CC} ${CFLAGS} ${DEFINE} newmail.c getopt.c expand.o \ ../src/string2.o -o ../bin/newmail ../bin/listalias: listalias.c -- Phil Hochstetler uunet!sequent!phil Sequent Computer Systems Beaverton, Oregon