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.