[comp.mail.elm] elm2.1PL1 patches for 4.3 BSD style flock mail delivery

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