[comp.sources.unix] v23i005: Deliver 2.0 patches, Part05/10

rsalz@bbn.com (Rich Salz) (08/31/90)

Submitted-by: Chip Salzenberg <tct!chip@uunet.uu.net>
Posting-number: Volume 23, Issue 5
Archive-name: deliver2.0pch/part05

Changes in patch #6 to Deliver 2.0:

1.  The UMASK value was interfering with the MBX_MODE (mailbox
    permissions) value.  Fixed.

2.  Logging was failing in interesting (!) ways on systems without
    three-argument open() and O_APPEND.  Fixed with a log lockfile.

3.  The log format has been adjusted to emphasize the difference
    between separate invocations of Deliver and recursive calls.

This patch contains changes to the following files:
	patchlevel.h
	config.h
	copymsg.c
	deliver.h
	main.c
	mbox.c
	subs.c
	sysdep.c

Index: patchlevel.h
Prereq: 5
***************
*** 1,1 ****
! #define PATCHLEVEL 5
--- 1,1 ----
! #define PATCHLEVEL 6

Index: config.h
***************
*** 1,3 ****
! /* $Header: config.h,v 2.6 89/12/14 17:42:25 network Exp $
   *
   * Deliver configuration.
--- 1,3 ----
! /* $Header: config.h,v 2.7 90/02/06 11:56:37 chip Exp $
   *
   * Deliver configuration.
***************
*** 4,7 ****
--- 4,12 ----
   *
   * $Log:	config.h,v $
+  * Revision 2.7  90/02/06  11:56:37  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.6  89/12/14  17:42:25  network
   * Rework setvbuf() configuration to avoid errors.
***************
*** 291,295 ****
   * Log file names.
   * Errors and warnings are output to stderr and to this file.
!  * To disable logging, don't define LOGFILE.
   */
  
--- 296,302 ----
   * Log file names.
   * Errors and warnings are output to stderr and to this file.
!  * To disable logging, don't define LOG.
!  * To disable error logging, don't define ERRLOG.
!  * Define LOGLOCK to be the temp file controlling access to log files.
   */
  
***************
*** 296,299 ****
--- 303,307 ----
  #define LOG             "/usr/adm/deliver.log"
  #define ERRLOG          "/usr/adm/deliver.errlog"
+ #define LOGLOCK         "/tmp/dl.loglock"
  
  /*----------------------------------------------------------------------

Index: copymsg.c
***************
*** 1,3 ****
! /* $Header: copymsg.c,v 2.3 89/11/27 14:18:29 network Exp $
   *
   * Take the message from standard input and write it to two temp files,
--- 1,3 ----
! /* $Header: copymsg.c,v 2.4 90/02/06 11:56:38 chip Exp $
   *
   * Take the message from standard input and write it to two temp files,
***************
*** 5,8 ****
--- 5,13 ----
   *
   * $Log:	copymsg.c,v $
+  * Revision 2.4  90/02/06  11:56:38  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.3  89/11/27  14:18:29  network
   * Strip trailing spaces from date on From_ line.
***************
*** 32,42 ****
  		&& (p)[3] == 'm' && (p)[4] == ' ')
  
- /*
-  * Local functions.
-  */
- 
- static  char    *tempfile();
- static  int     tcreate();
- 
  /*----------------------------------------------------------------------
   * Copy the message on the standard input to two temp files:
--- 37,40 ----
***************
*** 457,513 ****
  
  	return 0;
- }
- 
- /*----------------------------------------------------------------------
-  * Return a pointer to a temporary filename, or NULL if error.
-  */
- 
- static char *
- tempfile()
- {
- 	static char template[] = "/tmp/dl.XXXXXX";
- 	char    *f;
- 
- 	f = zalloc(32);
- 	(void) strcpy(f, template);
- 	if (mktemp(f) == NULL)
- 	{
- 		error("can't create temporary file");
- 		return NULL;
- 	}
- 	return f;
- }
- 
- /*----------------------------------------------------------------------
-  * Create a file, or complain if it doesn't work.
-  */
- 
- static int
- tcreate(name)
- char    *name;
- {
- 	int     fd;
- 
- #ifdef O_CREAT
- 	fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0);
- #else
- 	fd = creat(name, 0);
- #endif
- 	if (fd == -1)
- 	{
- 		syserr("can't create %s", name);
- 		return -1;
- 	}
- 
- #ifndef O_CREAT
- 	(void) close(fd);
- 	if ((fd = open(name, 2)) == -1)
- 	{
- 		syserr("can't re-open %s", name);
- 		return -1;
- 	}
- #endif
- 
- 	return fd;
  }
  
--- 455,458 ----

Index: deliver.h
***************
*** 1,3 ****
! /* $Header: deliver.h,v 2.5 89/11/10 12:23:51 network Exp $
   *
   * General pull-it-together include file.
--- 1,3 ----
! /* $Header: deliver.h,v 2.6 90/02/06 11:54:45 chip Exp $
   *
   * General pull-it-together include file.
***************
*** 4,7 ****
--- 4,12 ----
   *
   * $Log:	deliver.h,v $
+  * Revision 2.6  90/02/06  11:54:45  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.5  89/11/10  12:23:51  network
   * Handle recursion.
***************
*** 70,75 ****
  
  extern  FILE    *log;           /* File to log deliveries               */
  extern  FILE    *errlog;        /* File to log messages and errors      */
! extern  int     errused;        /* Error log used flag                  */
  
  extern  int     tty_input;      /* Is our input coming from a tty?      */
--- 75,81 ----
  
  extern  FILE    *log;           /* File to log deliveries               */
+ extern  char    *logfile;       /* Temporary file for log               */
  extern  FILE    *errlog;        /* File to log messages and errors      */
! extern  char    *errlogfile;    /* Temporary file for error log         */
  
  extern  int     tty_input;      /* Is our input coming from a tty?      */
***************
*** 94,97 ****
--- 100,104 ----
   */
  
+ char    *tempfile();
  char    *basename();
  char    *relpath();
***************
*** 105,108 ****
--- 112,116 ----
  CONTEXT *uid_context();
  
+ FILE    *ftcreate();
  FILE    *ct_popenv();
  int     ct_pclose();

Index: main.c
***************
*** 1,3 ****
! /* $Header: main.c,v 2.6 89/12/19 16:45:26 network Exp $
   *
   * A program to deliver local mail with some flexibility.
--- 1,3 ----
! /* $Header: main.c,v 2.7 90/02/06 11:56:40 chip Exp $
   *
   * A program to deliver local mail with some flexibility.
***************
*** 4,7 ****
--- 4,12 ----
   *
   * $Log:	main.c,v $
+  * Revision 2.7  90/02/06  11:56:40  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.6  89/12/19  16:45:26  network
   * Include <time.h> for the functions.
***************
*** 84,89 ****
  
  FILE    *log            = NULL;
  FILE    *errlog         = NULL;
! int     errused         = FALSE;
  
  int     tty_input       = FALSE;
--- 89,95 ----
  
  FILE    *log            = NULL;
+ char    *logfile        = NULL;
  FILE    *errlog         = NULL;
! char    *errlogfile     = NULL;
  
  int     tty_input       = FALSE;
***************
*** 260,275 ****
  	}
  
! #ifdef LOG
! 	/* If we're delivering and the log file exists, open it. */
  
! 	if (!dryrun && exists(LOG))
! 		log = fopen(LOG, "a");
  #endif
  
! #ifdef ERRLOG
! 	/* If we're delivering and not being verbose, open the error log. */
  
! 	if (!dryrun && !verbose)
! 		errlog = fopen(ERRLOG, "a");
  #endif
  
--- 266,289 ----
  	}
  
! #ifdef ERRLOG
! 	/* If we're delivering and not being verbose, keep an error log. */
  
! 	if (!dryrun && !verbose)
! 	{
! 		errlogfile = tempfile();
! 		if ((errlog = ftcreate(errlogfile)) == NULL)
! 			syserr("can't create %s", errlogfile);
! 	}
  #endif
  
! #ifdef LOG
! 	/* If we're delivering and the log file exists, keep data for it. */
  
! 	if (!dryrun && exists(LOG))
! 	{
! 		logfile = tempfile();
! 		if ((log = ftcreate(logfile)) == NULL)
! 			syserr("can't create %s", logfile);
! 	}
  #endif
  
***************
*** 545,550 ****
--- 559,568 ----
  int     code;
  {
+ 	/* Report vital statistics if something went wrong. */
+ 
  	errinfo();
  
+ 	/* Discard temporary files. */
+ 
  	if (! leavetemps)
  	{
***************
*** 560,565 ****
  	}
  
! 	errend();
  
  	exit(code);
  }
--- 578,597 ----
  	}
  
! 	/* Save temporary logs by appending to real logfiles. */
  
+ 	savelogs();
+ 
+ 	/* Discard temporary logs. */
+ 
+ 	if (! leavetemps)
+ 	{
+ 		if (logfile && unlink(logfile) == -1)
+ 			(void) syserr("can't remove %s", logfile);
+ 		if (errlogfile && unlink(errlogfile) == -1)
+ 			(void) syserr("can't remove %s", logfile);
+ 	}
+ 
+ 	/* "I am outa here." */
+ 
  	exit(code);
  }
***************
*** 624,628 ****
  		return;
  
! 	timestamp(log);
  
  	if (sender && *sender)
--- 656,660 ----
  		return;
  
! 	logstart(log);
  
  	if (sender && *sender)
***************
*** 639,643 ****
  	logstate("failed", ST_ERROR);
  
! 	(void) fflush(log);
  }
  
--- 671,675 ----
  	logstate("failed", ST_ERROR);
  
! 	logdone(log);
  }
  
***************
*** 700,703 ****
--- 732,833 ----
  
  	return count;
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Save log data in the real logfiles.
+  */
+ 
+ savelogs()
+ {
+ 	/* If logs weren't kept, forget it. */
+ 
+ 	if (!log && !errlog)
+ 		return;
+ 
+ 	/* If temporary logs contain anything, append them to real logs. */
+ 
+ 	if ((log && ftell(log) > 0)
+ 	 || (errlog && ftell(errlog) > 0))
+ 	{
+ 		if (create_lockfile(LOGLOCK) == 0)
+ 		{
+ 			applog(&log, LOG);
+ 			errdone();
+ 			applog(&errlog, ERRLOG);
+ 			(void) remove_lockfile(LOGLOCK);
+ 		}
+ 	}
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Append a temporary log file to a real logfile.
+  * We pass a FILE **, so that it can be set to NULL when closed;
+  * this is important, since errlog is used by syserr().
+  * Note:  The logfile is ass_u_med to be locked already!
+  */
+ 
+ applog(fpp, realfile)
+ FILE	**fpp;
+ char	*realfile;
+ {
+ 	FILE	*fp = fpp ? *fpp : NULL;
+ 	int	fd, realfd;
+ 
+ 	/* If log data weren't kept, never mind. */
+ 
+ 	if (fp == NULL)
+ 		return;
+ 
+ 	/* Flush buffered data. */
+ 
+ 	(void) fflush(fp);
+ 
+ 	/* If the file is empty, never mind. */
+ 
+ 	if (ftell(fp) == 0)
+ 	{
+ 		(void) fclose(fp);
+ 		*fpp = NULL;
+ 		return;
+ 	}
+ 
+ 	/* Get an fd and close the stream. */
+ 
+ 	if ((fd = dup(fileno(fp))) == -1)
+ 	{
+ 		syserr("can't dup log fd");
+ 		(void) fclose(fp);
+ 		*fpp = NULL;
+ 		return;
+ 	}
+ 	(void) fclose(fp);
+ 	*fpp = NULL;
+ 
+ 	/*
+ 	 * Open the real logfile, creating it if necessary.
+ 	 * Note that there is no race condition since the logs are locked.
+ 	 */
+ 
+ #ifdef O_CREAT
+ 	realfd = open(realfile, O_WRONLY|O_CREAT, 0666);
+ #else
+ 	if ((realfd = open(realfile, O_WRONLY)) == -1)
+ 		realfd = creat(realfile, 0666);
+ #endif
+ 	if (realfd == -1)
+ 		syserr("can't open %s for writing", logfile);
+ 	else
+ 	{
+ 		/* Append the temporary log to the real log. */
+ 
+ 		(void) lseek(fd, 0L, 0);
+ 		(void) lseek(realfd, 0L, 2);
+ 		(void) copyfd(fd, realfd);
+ 		(void) close(realfd);
+ 	}
+ 
+ 	/* Close the temporary log. */
+ 
+ 	(void) close(fd);
  }
  

Index: mbox.c
***************
*** 1,3 ****
! /* $Header: mbox.c,v 2.2 89/11/01 11:51:05 network Exp $
   *
   * Finally!  Put the message in the specified mailbox(es).
--- 1,3 ----
! /* $Header: mbox.c,v 2.3 90/02/06 11:56:42 chip Exp $
   *
   * Finally!  Put the message in the specified mailbox(es).
***************
*** 4,7 ****
--- 4,12 ----
   *
   * $Log:	mbox.c,v $
+  * Revision 2.3  90/02/06  11:56:42  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.2  89/11/01  11:51:05  network
   * Fix error code; unknown user is now reported correctly.
***************
*** 153,156 ****
--- 158,163 ----
  	while ((fd = open(mailbox, O_WRONLY)) == -1)
  	{
+ 		int	um;
+ 
  		if (errno != ENOENT)
  		{
***************
*** 159,173 ****
  		}
  
  #ifdef O_CREAT
  		fd = open(mailbox, O_WRONLY|O_CREAT|O_EXCL, MBX_MODE);
- 
- 		/* If it exists now, try open() again. */
- 		if (fd == -1 && errno == EEXIST)
- 			continue;
  #else
  		fd = creat(mailbox, MBX_MODE);
  #endif
  		if (fd == -1)
  		{
  			syserr("can't create %s", mailbox);
  			break;
--- 166,184 ----
  		}
  
+ 		um = umask(0);    /* save old umask; set it to zero */
  #ifdef O_CREAT
  		fd = open(mailbox, O_WRONLY|O_CREAT|O_EXCL, MBX_MODE);
  #else
  		fd = creat(mailbox, MBX_MODE);
  #endif
+ 		(void) umask(um); /* restore umask; ass_u_me errno unchanged */
+ 
  		if (fd == -1)
  		{
+ 			/* If the error is "file already there", try again. */
+ 			if (errno == EEXIST)
+ 				continue;
+ 
+ 			/* Something is very wrong... */
  			syserr("can't create %s", mailbox);
  			break;

Index: subs.c
***************
*** 1,3 ****
! /* $Header: subs.c,v 2.3 89/11/01 10:37:58 network Exp $
   *
   * Miscellaneous subroutines.
--- 1,3 ----
! /* $Header: subs.c,v 2.4 90/02/06 11:56:46 chip Exp $
   *
   * Miscellaneous subroutines.
***************
*** 4,7 ****
--- 4,12 ----
   *
   * $Log:	subs.c,v $
+  * Revision 2.4  90/02/06  11:56:46  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.3  89/11/01  10:37:58  network
   * Add exists() function.
***************
*** 34,37 ****
--- 39,117 ----
  
  	return (stat(path, &st) == 0);
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Return a pointer to a temporary filename, or NULL if error.
+  */
+ 
+ char *
+ tempfile()
+ {
+ 	static char template[] = "/tmp/dl.XXXXXX";
+ 	char    *f;
+ 
+ 	f = zalloc(32);
+ 	(void) strcpy(f, template);
+ 	if (mktemp(f) == NULL)
+ 	{
+ 		error("can't create temporary file");
+ 		return NULL;
+ 	}
+ 	return f;
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Create a file and return an fd, or complain if it doesn't work.
+  * The file is opened for read/write.
+  */
+ 
+ int
+ tcreate(name)
+ char    *name;
+ {
+ 	int     fd;
+ 
+ #ifdef O_CREAT
+ 	fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0);
+ #else
+ 	fd = creat(name, 0);
+ #endif
+ 	if (fd == -1)
+ 	{
+ 		syserr("can't create %s", name);
+ 		return -1;
+ 	}
+ 
+ #ifndef O_CREAT
+ 	(void) close(fd);
+ 	if ((fd = open(name, 2)) == -1)
+ 	{
+ 		syserr("can't re-open %s", name);
+ 		return -1;
+ 	}
+ #endif
+ 
+ 	return fd;
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Create a file and return a FILE *, or complain if it doesn't work.
+  * The file is opened for read/write.
+  */
+ 
+ FILE *
+ ftcreate(name)
+ char    *name;
+ {
+ 	FILE	*fp;
+ 	int	fd;
+ 
+ 	if ((fd = tcreate(name)) == -1)
+ 		return NULL;
+ 
+ 	if ((fp = fdopen(fd, "r+")) == NULL)
+ 		(void) close(fd);
+ 
+ 	return fp;
  }
  

Index: sysdep.c
***************
*** 1,3 ****
! /* $Header: sysdep.c,v 2.5 89/12/19 16:29:47 network Exp $
   *
   * Routines which are (or might well be) system-dependant.
--- 1,3 ----
! /* $Header: sysdep.c,v 2.6 90/02/06 11:56:43 chip Exp $
   *
   * Routines which are (or might well be) system-dependant.
***************
*** 6,9 ****
--- 6,14 ----
   *
   * $Log:	sysdep.c,v $
+  * Revision 2.6  90/02/06  11:56:43  chip
+  * Enforce MBX_MODE regardless of UMASK.
+  * Enforce ordered logging with a log lockfile.
+  * Revise log format.
+  * 
   * Revision 2.5  89/12/19  16:29:47  network
   * Make timezone handling portable to System V.
***************
*** 190,194 ****
  	/* If any errors have been logged, record the failed header. */
  
! 	if (errused)
  		errheader();
  }
--- 195,199 ----
  	/* If any errors have been logged, record the failed header. */
  
! 	if (ftell(errlog) > 0)
  		errheader();
  }
***************
*** 280,290 ****
  errstart()
  {
- 	/* For the sake of V7, manually seek to EOF. */
- 
- 	(void) fseek(errlog, 0L, 2);
- 
  	/* If we've already written a time stamp, don't do it again. */
  
! 	if (errused)
  		return;
  
--- 285,291 ----
  errstart()
  {
  	/* If we've already written a time stamp, don't do it again. */
  
! 	if (!errlog || ftell(errlog) > 0)
  		return;
  
***************
*** 291,295 ****
  	/* Write a time stamp and various useful info. */
  
! 	timestamp(errlog);
  	(void) fprintf(errlog, "process %d", getpid());
  	if (rec_parent > 0)
--- 292,296 ----
  	/* Write a time stamp and various useful info. */
  
! 	logstart(errlog);
  	(void) fprintf(errlog, "process %d", getpid());
  	if (rec_parent > 0)
***************
*** 296,303 ****
  		(void) fprintf(errlog, ", parent %d", rec_parent);
  	(void) fprintf(errlog, ": %s %s\n", progname, version);
- 
- 	/* Remember that we've written the time stamp. */
- 
- 	errused = TRUE;
  }
  
--- 297,300 ----
***************
*** 306,314 ****
   */
  
! errend()
  {
  	/* If we never wrote to the error log file, do nothing. */
  
! 	if (!errused)
  		return;
  
--- 303,311 ----
   */
  
! errdone()
  {
  	/* If we never wrote to the error log file, do nothing. */
  
! 	if (!errlog || ftell(errlog) == 0)
  		return;
  
***************
*** 319,330 ****
  		(void) fprintf(errlog, ", parent %d", rec_parent);
  	(void) fprintf(errlog, ": exit\n");
! 	(void) fflush(errlog);
  }
  
  /*----------------------------------------------------------------------
!  * Write a timestamp to the given file.
   */
  
! timestamp(fp)
  FILE    *fp;
  {
--- 316,329 ----
  		(void) fprintf(errlog, ", parent %d", rec_parent);
  	(void) fprintf(errlog, ": exit\n");
! 
! 	logdone(errlog);
  }
  
  /*----------------------------------------------------------------------
!  * Start a log entry.
!  * Various useful info goes here -- especially a timestamp.
   */
  
! logstart(fp)
  FILE    *fp;
  {
***************
*** 342,346 ****
  	if (rec_level)
  		(void) fprintf(fp, "[%d]", rec_level);
! 	(void) fputs("======================== ", fp);
  	(void) fprintf(fp, "%d %s %d, %02d:%02d:%02d %s\n",
  			lt->tm_mday, month[lt->tm_mon], lt->tm_year + 1900,
--- 341,347 ----
  	if (rec_level)
  		(void) fprintf(fp, "[%d]", rec_level);
! 	else
! 		(void) fputs("---", fp);
! 	(void) fputs("------------------------ ", fp);
  	(void) fprintf(fp, "%d %s %d, %02d:%02d:%02d %s\n",
  			lt->tm_mday, month[lt->tm_mon], lt->tm_year + 1900,
***************
*** 352,355 ****
--- 353,368 ----
  #endif
  			);
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Write a concluding marker to the given logfile.
+  * This marker separates instances of Deliver at recursion level zero.
+  */
+ 
+ logdone(fp)
+ FILE	*fp;
+ {
+ 	if (rec_level == 0)
+ 		(void) fputs("===========================\n\n", fp);
  }
  


exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.