From nobody Sun Apr 27 06:29:54 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 4ZlcBW1pWDz5vNJs; Sun, 27 Apr 2025 06:29:55 +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 4ZlcBW0T7tz3qZP; Sun, 27 Apr 2025 06:29:55 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1745735395; 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=IMKWYyUzSQZn/IL2ohvsNdu1J0DN4KojOSEW/UX79Hs=; b=aJAdzP+1x5puB45Mt6RgZIPR6RxmZ7P6EySx1agXLraY11P80LXOgVnD1WBCa8Es3uIX8A CxprQkz/V1E6h2aEVxyLVK1k0T3E0TlzqQJOvOoDJyGCmfNTPZywXw9atZkp7iSIXUQfeJ Gm9cSof60Xtm9ULSt8kita2GtgvMNOgDhCSv6hI1eq8E9kRrli4i+Ww4ZwyDBfUJ5DLit3 aggfh5XPQUb3AOVoRpYx+3WrBxtmKTrjhbalIIXekaUfKISmEMIkqZqFn72D9cO1vQ0tZs NkCJvyatsfVvskrF28q+wOMu9YomyMs/dkqjf8ZJTvItfL/iqNydg+lLFACBwg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1745735395; a=rsa-sha256; cv=none; b=Pp8DvzgL3zX8k4Pjj2Ys2d58UxHZeCtdN9X9CJvG5GDg82rVlsLMYimTeu0F/Ty5o3e/nY ZWIJGsnvs7rbqJAZrSJ5elHjk7rxNPCFG5l+QGvqrWMUuo0VbgtztyzkZ2D9T8nxm8tk73 kZWtbNdqP+yDg5aQEH3xYB1grqs+Gl5joNMug2GQHSgu5bmnMfcC7UG5/r38PhgeWdaTms ACEdKqR1soAT4VraHz4fYWZZrI1jEDyZBbvdDDlyqyJI/f+seFDXiFXsghYBChGWN7gd7H tDYDmHsDaqV3Swc1/Ue6ABPw4Q0TJgf+EntCn6OLwMCod4AfPxDkoYZcPbyeKw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1745735395; 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=IMKWYyUzSQZn/IL2ohvsNdu1J0DN4KojOSEW/UX79Hs=; b=D5VeHosYzD8cY1L3AIYLty5++iGARC1igKj2j1HOKiJrIiRMhA914qyDPlpspYYCaVBaJj 7oOrF1H5vU2DsWU9Aguatv87H1uf0blHRqIU+8xHg7Bh5dlIoMpxl8tcPjWVVnU0rpzm4G nOVzLwU7pnTq9QWW7ksnOpmsURcueZ1xYo7XXkEKM24/srwMf4yBoyc114NMnEuDpL9+a5 Yin8VmytAdbzs7Pm386/JMd/gOzWeH8xdTZVlS8O/NJtCkGbhaDF6S22/jhFH4R5RH/DTx O6X8mOzGvRjk0k4fNQspI/wkKwPX2/fW1CRyJ2vWoxSLeM/5DkcbJ1hRPGluhw== 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 4ZlcBV565SztpG; Sun, 27 Apr 2025 06:29:54 +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 53R6Tsbp053397; Sun, 27 Apr 2025 06:29:54 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53R6TsuF053394; Sun, 27 Apr 2025 06:29:54 GMT (envelope-from git) Date: Sun, 27 Apr 2025 06:29:54 GMT Message-Id: <202504270629.53R6TsuF053394@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 59597032c948 - main - 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/main X-Git-Reftype: branch X-Git-Commit: 59597032c948586257f123f57bbcfbad02a2cd1b Auto-Submitted: auto-generated The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=59597032c948586257f123f57bbcfbad02a2cd1b commit 59597032c948586257f123f57bbcfbad02a2cd1b Author: Dag-Erling Smørgrav AuthorDate: 2025-04-27 06:29:20 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-04-27 06:29:32 +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 --- etc/mtree/BSD.tests.dist | 2 + usr.bin/mail/Makefile | 5 ++ usr.bin/mail/collect.c | 34 ++++---- usr.bin/mail/tests/Makefile | 4 + usr.bin/mail/tests/mail_sigint_test.c | 149 ++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 14 deletions(-) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 20744e7b944a..673452434080 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -1165,6 +1165,8 @@ .. m4 .. + mail + .. mkimg .. mktemp diff --git a/usr.bin/mail/Makefile b/usr.bin/mail/Makefile index c20060d88ebf..0a27b5c5a637 100644 --- a/usr.bin/mail/Makefile +++ b/usr.bin/mail/Makefile @@ -1,3 +1,5 @@ +.include + CONFS= misc/mail.rc PROG= mail SRCS= version.c cmd1.c cmd2.c cmd3.c cmdtab.c collect.c edit.c fio.c \ @@ -17,4 +19,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 0c310b15b234..2423bcf7b262 100644 --- a/usr.bin/mail/collect.c +++ b/usr.bin/mail/collect.c @@ -79,16 +79,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; @@ -473,11 +477,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/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..76bf9b19b7f1 --- /dev/null +++ b/usr.bin/mail/tests/mail_sigint_test.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#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]; + 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 || + pipe2(spd, O_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]); + /* 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; + for (;;) { + if (poll(fds, 2, 1000) < 0) + atf_tc_fail("failed to poll"); + if (fds[0].revents == POLLIN && olen < sizeof(obuf)) { + rlen = read(opd[0], obuf + olen, sizeof(obuf) - olen - 1); + if (rlen < 0) + atf_tc_fail("failed to read"); + olen += rlen; + } + if (fds[1].revents == POLLIN && elen < sizeof(ebuf)) { + rlen = read(epd[0], ebuf + elen, sizeof(ebuf) - elen - 1); + if (rlen < 0) + atf_tc_fail("failed to read"); + elen += rlen; + } + if (elen > 0 && kc == 1) { + kill(pid, SIGINT); + kc++; + } + 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)); + ATF_CHECK_INTEQ(0, 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)); + 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()); +}