Backport of upstream commit c5e7490 mail: fix exit code handling of sendmail cmd Prior to this commit the return code of the pclose function was assumed to be the exit code of the process. However, the returned value as specified in wait(2) is a bit packed integer and must be interpreted with the provided macros. This has no effect in success cases as the integer is still zero, but in failure cases the wrong value is used, since the 8 least significant bits contain the status code. After this commit we use the macros to obtain the status code, which fixes the EX_TEMPFAIL conditional. For WIN32 the TSRM popen_ex and pclose function are used. The return value of TSRM's pclose is not bit packed so we only check if the return value is non-zero, which should solve, #43327, https://bugs.php.net/bug.php?id=43327 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -25,6 +25,10 @@ #include "ext/date/php_date.h" #include "zend_smart_str.h" +#ifdef HAVE_SYS_WAIT_H +#include +#endif + #if HAVE_SYSEXITS_H #include #endif @@ -518,6 +522,7 @@ fprintf(sendmail, "%s\r\n", hdr); } fprintf(sendmail, "\r\n%s\r\n", message); +#ifdef PHP_WIN32 ret = pclose(sendmail); #if PHP_SIGCHILD @@ -525,10 +530,27 @@ signal(SIGCHLD, sig_handler); } #endif - -#ifdef PHP_WIN32 - if (ret == -1) #else + int wstatus = pclose(sendmail); +#if PHP_SIGCHILD + if (sig_handler) { + signal(SIGCHLD, sig_handler); + } +#endif + /* Determine the wait(2) exit status */ + if (wstatus == -1) { + MAIL_RET(0); + } else if (WIFSIGNALED(wstatus)) { + MAIL_RET(0); + } else { + if (WIFEXITED(wstatus)) { + ret = WEXITSTATUS(wstatus); + } else { + MAIL_RET(0); + } + } +#endif + #if defined(EX_TEMPFAIL) if ((ret != EX_OK)&&(ret != EX_TEMPFAIL)) #elif defined(EX_OK) @@ -536,7 +558,6 @@ #else if (ret != 0) #endif -#endif { MAIL_RET(0); } else { --- /dev/null +++ b/ext/standard/tests/mail/mail_variation3.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test mail() function : variation sendmail temp fail +--INI-- +sendmail_path=exit 75 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +*** Testing mail() : variation *** +bool(true) --- /dev/null +++ b/ext/standard/tests/mail/mail_variation4.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test mail() function : variation sigterm +--INI-- +sendmail_path="kill \$\$" +--SKIPIF-- + +--FILE-- + +--EXPECT-- +*** Testing mail() : variation *** +bool(false) --- /dev/null +++ b/ext/standard/tests/mail/mail_variation5.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test mail() function : variation non-zero exit +--INI-- +sendmail_path="exit 123" +--SKIPIF-- + +--FILE-- + +--EXPECT-- +*** Testing mail() : variation *** +bool(false)