Arrange for output from Perl's "warn" to go to the mainlog by default.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 27 Jan 2005 15:00:38 +0000 (15:00 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Thu, 27 Jan 2005 15:00:38 +0000 (15:00 +0000)
doc/doc-src/spec.src
doc/doc-txt/ChangeLog
src/src/daemon.c
src/src/perl.c

index 5ecbd9e9eef352d7cd0d019074bdb27de4f217d1..69ebca07deb03565ece8599542dcccee8ce5f770 100644 (file)
@@ -1,4 +1,4 @@
-. $Cambridge: exim/doc/doc-src/spec.src,v 1.5 2005/01/27 10:25:35 ph10 Exp $
+. $Cambridge: exim/doc/doc-src/spec.src,v 1.6 2005/01/27 15:00:38 ph10 Exp $
 .
 .set version "4.50"
 .set previousversion "4.40"
 .
 .set version "4.50"
 .set previousversion "4.40"
@@ -10673,21 +10673,29 @@ terminating newline.
 
 .em
 .section Use of standard output and error by Perl
 
 .em
 .section Use of standard output and error by Perl
+.index Perl||standard output and error
 You should not write to the standard error or output streams from within your 
 You should not write to the standard error or output streams from within your 
-Perl code, as it is not defined how these are set up. In versions of Exim up to 
-at least 4.50, it is possible for the standard output or error to refer to the 
-SMTP connection during message reception. Writing to this stream is likely to 
-cause chaos. Something may be done about this in later releases.
-
-Unfortunately, the Perl \warn\ statment writes to the standard error stream, 
-and this may be embedded in Perl modules that you use, but over which you have 
-no control. One way round this is to ensure that the following Perl magic is 
-obeyed before \warn\ is used:
-.display asis
-$SIG{__WARN__} = sub { Exim::log_write($_[0]) };
-.endd
-This causes the output of the \warn\ statement to be written to Exim's log 
-file.
+Perl code, as it is not defined how these are set up. In versions of Exim  
+before 4.50, it is possible for the standard output or error to refer to the 
+SMTP connection during message reception via the daemon. Writing to this stream
+is certain to cause chaos. From Exim 4.50 onwards, the standard output and
+error streams are connected to \(/dev/null)\ in the daemon. The chaos is 
+avoided, but the output is lost.
+
+.index Perl||\warn\, use of
+The Perl \warn\ statement writes to the standard error stream by default. Calls 
+to \warn\ may be embedded in Perl modules that you use, but over which you have
+no control. When Exim starts up the Perl interpreter, it arranges for output
+from the \warn\ statement to be written to the Exim main log. You can change 
+this by including appropriate Perl magic somewhere in your Perl code. For 
+example, to discard \warn\ output completely, you need this:
+.display asis
+$SIG{__WARN__} = sub { };
+.endd
+Whenever a \warn\ is obeyed, the anonymous subroutine is called. In this 
+example, the code for the subroutine is empty, so it does nothing, but you can
+include any Perl code that you like. The text of the \warn\ message is passed
+as the first subroutine argument.
 .nem
 
 
 .nem
 
 
index 799999e70e52643c8c353f77db8bbfeef6db1120..eaec31c78f83253c7eedac00f304885797c1c364 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.75 2005/01/27 10:26:14 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.76 2005/01/27 15:00:39 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -351,6 +351,16 @@ Exim version 4.50
 
       verify = header_sender/callout=defer_ok
 
 
       verify = header_sender/callout=defer_ok
 
+75. A backgrounded daemon closed stdin/stdout/stderr on entry; this meant that
+    those file descriptors could be used for SMTP connections. If anything
+    wrote to stderr (the example that came up was "warn" in embedded Perl), it
+    could be sent to the SMTP client, causing chaos. The daemon now opens
+    stdin, stdout, and stderr to /dev/null when it puts itself into the
+    background.
+
+76. Arrange for output from Perl's "warn" command to be written to Exim's main
+    log by default. The user can override this with suitable Perl magic.
+
 
 ----------------------------------------------------
 See the note above about the 4.44 and 4.50 releases.
 
 ----------------------------------------------------
 See the note above about the 4.44 and 4.50 releases.
index 1c274d732008b0cda04087211aefb8bd098946eb..88dd69d21c02318d3d00db631fbddf1576e65a0b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/daemon.c,v 1.5 2005/01/04 10:37:55 ph10 Exp $ */
+/* $Cambridge: exim/src/src/daemon.c,v 1.6 2005/01/27 15:00:39 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1124,26 +1124,35 @@ if (daemon_listen)
     }
   }
 
     }
   }
 
-/* We now close all open file descriptors that we know about, and disconnect
-from the controlling terminal, unless background_daemon is unset. This is
-always unset when debugging, but can also be forced. Most modern Unixes seem to
-have setsid() for getting rid of the controlling terminal. For any OS that
-doesn't, setsid() can be #defined as a no-op, or as something else. */
+/* The variable background_daemon is always false when debugging, but
+can also be forced false in order to keep a non-debugging daemon in the
+foreground. If background_daemon is true, close all open file descriptors that
+we know about, but then re-open stdin, stdout, and stderr to /dev/null.
+
+This is protection against any called functions (in libraries, or in
+Perl, or whatever) that think they can write to stderr (or stdout). Before this
+was added, it was quite likely that an SMTP connection would use one of these
+file descriptors, in which case writing random stuff to it caused chaos.
+
+Then disconnect from the controlling terminal, Most modern Unixes seem to have
+setsid() for getting rid of the controlling terminal. For any OS that doesn't,
+setsid() can be #defined as a no-op, or as something else. */
 
 if (background_daemon)
   {
 
 if (background_daemon)
   {
-  log_close_all();  /* Just in case anything was logged earlier */
-  search_tidyup();  /* Just in case any were used in reading the config. */
-  close(0);         /* Get rid of stdin/stdout/stderr */
+  log_close_all();    /* Just in case anything was logged earlier */
+  search_tidyup();    /* Just in case any were used in reading the config. */
+  close(0);           /* Get rid of stdin/stdout/stderr */
   close(1);
   close(2);
   close(1);
   close(2);
+  exim_nullstd();     /* Connect stdin/stdout/stderr to /dev/null */ 
   log_stderr = NULL;  /* So no attempt to copy paniclog output */
 
   /* If the parent process of this one has pid == 1, we are re-initializing the
   log_stderr = NULL;  /* So no attempt to copy paniclog output */
 
   /* If the parent process of this one has pid == 1, we are re-initializing the
-  daemon as the result of a SIGHUP. In this case, there is no need to do any
-  forking, because the controlling terminal has long gone. Otherwise, fork,
-  in case current process is a process group leader (see 'man setsid' for an
-  explanation). */
+  daemon as the result of a SIGHUP. In this case, there is no need to do 
+  anything, because the controlling terminal has long gone. Otherwise, fork, in
+  case current process is a process group leader (see 'man setsid' for an
+  explanation) before calling setsid(). */
 
   if (getppid() != 1)
     {
 
   if (getppid() != 1)
     {
index a22fe6f401ff98d86189c0d88f614f4da92f93b8..5bb7ad3608fd0dd7c312910ffbbe7a6520f35dee 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/perl.c,v 1.2 2004/12/20 11:46:21 ph10 Exp $ */
+/* $Cambridge: exim/src/src/perl.c,v 1.3 2005/01/27 15:00:39 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -109,6 +109,21 @@ init_perl(uschar *startup_code)
   perl_run(interp_perl);
     {
     dSP;
   perl_run(interp_perl);
     {
     dSP;
+
+    /*********************************************************************/
+    /* These lines by PH added to make "warn" output go to the Exim log; I
+    hope this doesn't break anything. */
+     
+    sv = newSVpv(
+      "$SIG{__WARN__} = sub { my($s) = $_[0];"
+      "$s =~ s/\\n$//;" 
+      "Exim::log_write($s) };", 0);
+    PUSHMARK(SP);
+    perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);
+    SvREFCNT_dec(sv);
+    if (SvTRUE(ERRSV)) return US SvPV(ERRSV, len);
+    /*********************************************************************/
     sv = newSVpv(CS startup_code, 0);
     PUSHMARK(SP);
     perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);
     sv = newSVpv(CS startup_code, 0);
     PUSHMARK(SP);
     perl_eval_sv(sv, G_SCALAR|G_DISCARD|G_KEEPERR);