From nobody Wed May 21 17:47:36 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4b2f5N2NFvz5wGpc; Wed, 21 May 2025 17:47:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4b2f5N1Wp9z43Wr; Wed, 21 May 2025 17:47:36 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1747849656; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=cqsRTPlwGZ7chIyCTDXCsdQmJwmtt251nW0oRAX+Eww=; b=KfSTKEUO7dwg+s6FsdcaB7zB86WeefLML3Tb9+Nh20SCbjhVMAzgspJRugzZHq8+OMsE5S mt+NZv4/ct+/mD7wqka9RycxUfC+UJvlBGbSBqvEnqGgb5YvGJD/JVq7HpdRPr5QHzM3wM XbYcVA8gU5kUcCcDV4EWrAx/JthGZD5zStBKfp3v8h8f8805y/RZCPKYz0qe8W+adUsl7G YqZWyd6+MLEDJwriaUlu/Bx5Er+ZsVssRQ/77fU938p2lajfWiCFCSUg1sevmM/WVgBw6y qsBO9EKag9Bm/Mq4kzoXYoQ/oW+y9hDADTUJG0vz80jOq2p1RMXasOi45h0kdQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1747849656; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=cqsRTPlwGZ7chIyCTDXCsdQmJwmtt251nW0oRAX+Eww=; b=XbcEYQdVqE3WcUb1NGVQLTPPhdhuqhPcZjoC6ijndVg+1QvBjusLjz/dKy6Dt4dz6gYMM2 OxUve7Fn9G7TEJVK9cNTj5nepuiMeRSVpvNemCcGRog7lqczAuyaryZ9opZ2TCwBqLUmu9 4Ps8NPCbl712OW8csQynPtCC2SMilnHV10uM3EDGuQ4IAuNwyLjcBeiN/llQ8bL7TUI3yt nLQiLdalHBXRRm31AEaKLCZxLO9IfPnSt3tzJ8LxxYrwoEQaTj4vNZptXxHvNVjAIdK7Iu 8hYmvjtVVAlK2QdD1LI5LIfwHTWlN826ljjKtCLKybLB2d6Q7yVKClbGu0E6cQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1747849656; a=rsa-sha256; cv=none; b=Of8vxmtNKFmUEDUvgqeDJY1mA8R37StwnWwirBnr33mxYQ7GuM1OHOdFKfaPu7ifJ/w0cs WBSfmlGyxCNcTaFWCx9mYXwFiBLQbl0ytTdnmTOHIKWMaFCUGSWBViS/4sR6zYbjYZrj5q GiwZSYFNHaOkFPWgTUu0P8FE6ihdwhpG2Kjpfrul/DthUgDL8baJqFtGpGDeHZjCgBoDq7 xsczgbEL/TVeZ7DeCv4oNhGRy/Fe0X1DIeig5iJYu8zdeM1LUrQiFUI45x6AadFncU8/aT b8Ekero/bC3B/9NJCygQMhZqb7zxxSnpLhOsjuqG+vY18Uc4Pw3QKClAs7mXhQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4b2f5N174qzll2; Wed, 21 May 2025 17:47:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 54LHlaYH074894; Wed, 21 May 2025 17:47:36 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 54LHlaZ5074891; Wed, 21 May 2025 17:47:36 GMT (envelope-from git) Date: Wed, 21 May 2025 17:47:36 GMT Message-Id: <202505211747.54LHlaZ5074891@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 12666df00a74 - stable/14 - mail: Don't trap signals we shouldn't. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 12666df00a745c64d65c7248f278001b9dbfd937 Auto-Submitted: auto-generated The branch stable/14 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=12666df00a745c64d65c7248f278001b9dbfd937 commit 12666df00a745c64d65c7248f278001b9dbfd937 Author: Dag-Erling Smørgrav AuthorDate: 2025-04-27 06:29:20 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-05-21 17:33:08 +0000 mail: Don't trap signals we shouldn't. When in interactive mode, trap SIGINT, SIGHUP, and tty-related signals. Otherwise, leave signals untouched as required by POSIX. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D50011 (cherry picked from commit 59597032c948586257f123f57bbcfbad02a2cd1b) mail: Exit non-zero on failure to collect mail. While here, avoid non-portable `pipe2()` in the regression test. Fixes: 59597032c948 MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D50069 (cherry picked from commit 09bc6a5d5b3333bc91e5f9fdf1e7bb282c4aea5a) mail: Further refine the SIGINT test. * Wait at least 1-2 s before sending the second SIGINT. * If the child is still running after 15 s, send a SIGKILL. * Improve the exit status checks. Fixes: 59597032c948 MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D50092 (cherry picked from commit 42fd47ef81138ae53ba77add5a400f67af8e6263) --- etc/mtree/BSD.tests.dist | 2 + usr.bin/mail/Makefile | 4 + usr.bin/mail/collect.c | 34 +++++--- usr.bin/mail/send.c | 4 +- usr.bin/mail/tests/Makefile | 4 + usr.bin/mail/tests/mail_sigint_test.c | 157 ++++++++++++++++++++++++++++++++++ 6 files changed, 190 insertions(+), 15 deletions(-) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index a909ea3714d3..bf327b14c306 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -1109,6 +1109,8 @@ .. m4 .. + mail + .. mkimg .. mktemp diff --git a/usr.bin/mail/Makefile b/usr.bin/mail/Makefile index e5b0d8b3a3a6..bbbcf6c892b1 100644 --- a/usr.bin/mail/Makefile +++ b/usr.bin/mail/Makefile @@ -1,4 +1,5 @@ # @(#)Makefile 8.2 (Berkeley) 1/25/94 +.include CONFS= misc/mail.rc PROG= mail @@ -19,4 +20,7 @@ etc-mailrc: cd ${.CURDIR}/misc; ${INSTALL} -o root -g wheel \ -m 644 ${EFILES} ${DESTDIR}/etc +HAS_TESTS= +SUBDIR.${MK_TESTS}= tests + .include diff --git a/usr.bin/mail/collect.c b/usr.bin/mail/collect.c index ccb3b60bec2b..e6a6337bcdb0 100644 --- a/usr.bin/mail/collect.c +++ b/usr.bin/mail/collect.c @@ -85,16 +85,20 @@ collect(struct header *hp, int printheaders) * until we're in the main loop. */ (void)sigemptyset(&nset); - (void)sigaddset(&nset, SIGINT); - (void)sigaddset(&nset, SIGHUP); + if (value("interactive") != NULL) { + (void)sigaddset(&nset, SIGINT); + (void)sigaddset(&nset, SIGHUP); + } (void)sigprocmask(SIG_BLOCK, &nset, NULL); - if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) - (void)signal(SIGINT, collint); - if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) - (void)signal(SIGHUP, collhup); - savetstp = signal(SIGTSTP, collstop); - savettou = signal(SIGTTOU, collstop); - savettin = signal(SIGTTIN, collstop); + if (value("interactive") != NULL) { + if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) + (void)signal(SIGINT, collint); + if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) + (void)signal(SIGHUP, collhup); + savetstp = signal(SIGTSTP, collstop); + savettou = signal(SIGTTOU, collstop); + savettin = signal(SIGTTIN, collstop); + } if (setjmp(collabort) || setjmp(colljmp)) { (void)rm(tempname); goto err; @@ -479,11 +483,13 @@ out: rewind(collf); noreset--; (void)sigprocmask(SIG_BLOCK, &nset, NULL); - (void)signal(SIGINT, saveint); - (void)signal(SIGHUP, savehup); - (void)signal(SIGTSTP, savetstp); - (void)signal(SIGTTOU, savettou); - (void)signal(SIGTTIN, savettin); + if (value("interactive") != NULL) { + (void)signal(SIGINT, saveint); + (void)signal(SIGHUP, savehup); + (void)signal(SIGTSTP, savetstp); + (void)signal(SIGTTOU, savettou); + (void)signal(SIGTTIN, savettin); + } (void)sigprocmask(SIG_UNBLOCK, &nset, NULL); return (collf); } diff --git a/usr.bin/mail/send.c b/usr.bin/mail/send.c index 002157ba55cb..395b42c1e749 100644 --- a/usr.bin/mail/send.c +++ b/usr.bin/mail/send.c @@ -299,8 +299,10 @@ mail1(struct header *hp, int printheaders) * Collect user's mail from standard input. * Get the result as mtf. */ - if ((mtf = collect(hp, printheaders)) == NULL) + if ((mtf = collect(hp, printheaders)) == NULL) { + senderr++; return; + } if (value("interactive") != NULL) { if (value("askcc") != NULL || value("askbcc") != NULL) { if (value("askcc") != NULL) diff --git a/usr.bin/mail/tests/Makefile b/usr.bin/mail/tests/Makefile new file mode 100644 index 000000000000..cb194b3da1f1 --- /dev/null +++ b/usr.bin/mail/tests/Makefile @@ -0,0 +1,4 @@ +PACKAGE= tests +ATF_TESTS_C+= mail_sigint_test + +.include diff --git a/usr.bin/mail/tests/mail_sigint_test.c b/usr.bin/mail/tests/mail_sigint_test.c new file mode 100644 index 000000000000..ace5f714c459 --- /dev/null +++ b/usr.bin/mail/tests/mail_sigint_test.c @@ -0,0 +1,157 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define MAILX "mailx" +#define BODY "hello\n" +#define BODYLEN (sizeof(BODY) - 1) + +/* + * When interactive, mailx(1) should print a message on receipt of SIGINT, + * then exit cleanly on receipt of a second. + * + * When not interactive, mailx(1) should terminate on receipt of SIGINT. + */ +static void +mailx_sigint(bool interactive) +{ + char obuf[1024] = ""; + char ebuf[1024] = ""; + struct pollfd fds[2]; + int ipd[2], opd[2], epd[2], spd[2]; + time_t start, now; + size_t olen = 0, elen = 0; + ssize_t rlen; + pid_t pid; + int kc, status; + + /* input, output, error, sync pipes */ + if (pipe(ipd) != 0 || pipe(opd) != 0 || pipe(epd) != 0 || + pipe(spd) != 0 || fcntl(spd[1], F_SETFD, FD_CLOEXEC) != 0) + atf_tc_fail("failed to pipe"); + /* fork child */ + if ((pid = fork()) < 0) + atf_tc_fail("failed to fork"); + if (pid == 0) { + /* child */ + dup2(ipd[0], STDIN_FILENO); + close(ipd[0]); + close(ipd[1]); + dup2(opd[1], STDOUT_FILENO); + close(opd[0]); + close(opd[1]); + dup2(epd[1], STDERR_FILENO); + close(epd[0]); + close(epd[1]); + close(spd[0]); + /* force dead.letter to go to cwd */ + setenv("HOME", ".", 1); + /* exec mailx */ + execlp(MAILX, + MAILX, + interactive ? "-Is" : "-s", + "test", + "test@example.com", + NULL); + _exit(2); + } + /* parent */ + close(ipd[0]); + close(opd[1]); + close(epd[1]); + close(spd[1]); + /* block until child execs or exits */ + (void)read(spd[0], &spd[1], sizeof(spd[1])); + /* send one line of input */ + ATF_REQUIRE_INTEQ(BODYLEN, write(ipd[1], BODY, BODYLEN)); + /* give it a chance to process */ + poll(NULL, 0, 2000); + /* send first SIGINT */ + ATF_CHECK_INTEQ(0, kill(pid, SIGINT)); + kc = 1; + /* receive output until child terminates */ + fds[0].fd = opd[0]; + fds[0].events = POLLIN; + fds[1].fd = epd[0]; + fds[1].events = POLLIN; + time(&start); + for (;;) { + ATF_REQUIRE(poll(fds, 2, 1000) >= 0); + if (fds[0].revents == POLLIN && olen < sizeof(obuf)) { + rlen = read(opd[0], obuf + olen, sizeof(obuf) - olen - 1); + ATF_REQUIRE(rlen >= 0); + olen += rlen; + } + if (fds[1].revents == POLLIN && elen < sizeof(ebuf)) { + rlen = read(epd[0], ebuf + elen, sizeof(ebuf) - elen - 1); + ATF_REQUIRE(rlen >= 0); + elen += rlen; + } + time(&now); + if (now - start > 1 && elen > 0 && kc == 1) { + ATF_CHECK_INTEQ(0, kill(pid, SIGINT)); + kc++; + } + if (now - start > 15 && kc > 0) { + (void)kill(pid, SIGKILL); + kc = -1; + } + if (waitpid(pid, &status, WNOHANG) == pid) + break; + } + close(ipd[1]); + close(opd[0]); + close(epd[0]); + close(spd[0]); + if (interactive) { + ATF_CHECK(WIFEXITED(status)); + if (WIFEXITED(status)) + ATF_CHECK_INTEQ(1, WEXITSTATUS(status)); + ATF_CHECK_INTEQ(2, kc); + ATF_CHECK_STREQ("", obuf); + ATF_CHECK_MATCH("Interrupt -- one more to kill letter", ebuf); + atf_utils_compare_file("dead.letter", BODY); + } else { + ATF_CHECK(WIFSIGNALED(status)); + if (WIFSIGNALED(status)) + ATF_CHECK_INTEQ(SIGINT, WTERMSIG(status)); + ATF_CHECK_INTEQ(1, kc); + ATF_CHECK_STREQ("", obuf); + ATF_CHECK_STREQ("", ebuf); + ATF_CHECK_INTEQ(-1, access("dead.letter", F_OK)); + } +} + + +ATF_TC_WITHOUT_HEAD(mail_sigint_interactive); +ATF_TC_BODY(mail_sigint_interactive, tc) +{ + mailx_sigint(true); +} + +ATF_TC_WITHOUT_HEAD(mail_sigint_noninteractive); +ATF_TC_BODY(mail_sigint_noninteractive, tc) +{ + mailx_sigint(false); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, mail_sigint_interactive); + ATF_TP_ADD_TC(tp, mail_sigint_noninteractive); + return (atf_no_error()); +}