X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/921b12ca0c361b9c543368edf057712afa02ca14..1ac6b2e7857d7b6645dbd09047c4c2ac3b6cef1d:/src/src/log.c diff --git a/src/src/log.c b/src/src/log.c index 231db6581..7af92818e 100644 --- a/src/src/log.c +++ b/src/src/log.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/log.c,v 1.15 2010/06/06 00:27:52 pdp Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2009 */ +/* Copyright (c) University of Cambridge 1995 - 2012 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for writing log files. The code for maintaining datestamped @@ -482,6 +480,11 @@ log, which can happen if a disk gets full or a file gets too large or whatever. We try to save the relevant message in the panic_save buffer before crashing out. +The potential invoker should probably not call us for EINTR -1 writes. But +otherwise, short writes are bad as we don't do non-blocking writes to fds +subject to flow control. (If we do, that's new and the logic of this should +be reconsidered). + Arguments: name the name of the log being written length the string length being written @@ -510,6 +513,49 @@ log_write(0, LOG_PANIC_DIE, "failed to write to %s: length=%d result=%d " +/************************************************* +* Write to an fd, retrying after signals * +*************************************************/ + +/* Basic write to fd for logs, handling EINTR. + +Arguments: + fd the fd to write to + buf the string to write + length the string length being written + +Returns: + length actually written, persisting an errno from write() +*/ +ssize_t +write_to_fd_buf(int fd, const uschar *buf, size_t length) +{ +ssize_t wrote; +size_t total_written = 0; +const uschar *p = buf; +size_t left = length; + +while (1) + { + wrote = write(fd, p, left); + if (wrote == (ssize_t)-1) + { + if (errno == EINTR) continue; + return wrote; + } + total_written += wrote; + if (wrote == left) + break; + else + { + p += wrote; + left -= wrote; + } + } +return total_written; +} + + /************************************************* * Write message to log file * *************************************************/ @@ -571,8 +617,9 @@ void log_write(unsigned int selector, int flags, const char *format, ...) { uschar *ptr; -int length, rc; +int length; int paniclogfd; +ssize_t written_len; va_list ap; /* If panic_recurseflag is set, we have failed to open the panic log. This is @@ -715,7 +762,7 @@ DEBUG(D_any|D_v) } } - sprintf(CS ptr, "%s%s%s%s%s\n ", + sprintf(CS ptr, "%s%s%s%s\n ", ((flags & LOG_MAIN) != 0)? " MAIN" : "", ((flags & LOG_PANIC) != 0)? " PANIC" : "", ((flags & LOG_PANIC_DIE) == LOG_PANIC_DIE)? " DIE" : "", @@ -888,9 +935,10 @@ if ((flags & LOG_MAIN) != 0 && /* Failing to write to the log is disastrous */ - if ((rc = write(mainlogfd, log_buffer, length)) != length) + written_len = write_to_fd_buf(mainlogfd, log_buffer, length); + if (written_len != length) { - log_write_failed(US"main log", length, rc); + log_write_failed(US"main log", length, written_len); /* That function does not return */ } } @@ -1010,9 +1058,10 @@ if ((flags & LOG_REJECT) != 0) if (fstat(rejectlogfd, &statbuf) >= 0) rejectlog_inode = statbuf.st_ino; } - if ((rc = write(rejectlogfd, log_buffer, length)) != length) + written_len = write_to_fd_buf(rejectlogfd, log_buffer, length); + if (written_len != length) { - log_write_failed(US"reject log", length, rc); + log_write_failed(US"reject log", length, written_len); /* That function does not return */ } } @@ -1044,14 +1093,18 @@ if ((flags & LOG_PANIC) != 0) panic_recurseflag = FALSE; if (panic_save_buffer != NULL) - (void) write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer)); + { + int i = write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer)); + i = i; /* compiler quietening */ + } - if ((rc = write(paniclogfd, log_buffer, length)) != length) + written_len = write_to_fd_buf(paniclogfd, log_buffer, length); + if (written_len != length) { int save_errno = errno; write_syslog(LOG_CRIT, log_buffer); sprintf(CS log_buffer, "write failed on panic log: length=%d result=%d " - "errno=%d (%s)", length, rc, save_errno, strerror(save_errno)); + "errno=%d (%s)", length, (int)written_len, save_errno, strerror(save_errno)); write_syslog(LOG_CRIT, log_buffer); flags |= LOG_PANIC_DIE; } @@ -1256,7 +1309,7 @@ misconfiguration. The first use of this is in ACL logic, "control = debug/tag=foo/opts=+expand" which can be combined with conditions, etc, to activate extra logging only -for certain sources. */ +for certain sources. The second use is inetd wait mode debug preservation. */ void debug_logging_activate(uschar *tag_name, uschar *opts) @@ -1266,7 +1319,7 @@ int fd = -1; if (debug_file) { debug_printf("DEBUGGING ACTIVATED FROM WITHIN CONFIG.\n" - "DEBUG: Tag=\"%s\" Opts=\"%s\"\n", tag_name, opts); + "DEBUG: Tag=\"%s\" Opts=\"%s\"\n", tag_name, opts ? opts : US""); return; }