From nobody Tue Mar 10 10:18:51 2026 X-Original-To: dev-commits-src-main@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 4fVVGN1zjwz6VNyG for ; Tue, 10 Mar 2026 10:18:52 +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 "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fVVGN19k0z3vLR for ; Tue, 10 Mar 2026 10:18:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1773137932; 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=+sPKo20/r4fsNFw/lfzGX7vZQSn+QH+HelMisTQzFnc=; b=sTje4YX1HFwzxv6HHMmdVoWq3H3kVLK773EKrpQcSA9Gu2acpLl/X+B2sSHMofsVbRv7Um NXKfcSIxBKL+0Zk1Sj5uTtdoq8TJ0m3MH+eDRLF7GtoyQQRFyRtuydAlJNb4eMPfBYMmMF +8rqfuhtQRDpkuVmHAsiElmk1HOyN2QM0dNJIRZ3tfDr+1dMrBWpLkuu5FN5g7p20uz8b4 OSOaMIY0fS2tKf/ZEKAzw70CrSRoZBFpu7HZv6gOEMd7YOUGueR9t6FgmND8iSw0jruxw+ 1uf4VtwbMNi0D66hN8jnwkrHw0JgqfXWZcaIFJf+lwzUKNiTvRjO1euK0ASkcg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1773137932; a=rsa-sha256; cv=none; b=Scn2CRkeqQMcTspAQ96btmp/Q/KxxMkTLBIlPL5agOi5JZCy9vyNwbjV4+amjOoK5d35yj 5+SlHnrTuTqM7787N9v1iKYejh68cft7bMUhb6GnWV1rpINwBEeQ3TzdXrHknDGfce9qiw vLkgBYdCTUVSXSWlNutZb+NaDjMe+hb0WqzYdHjrJIeXSFbiIGmJbGLLgx5IawI7+NP8dA RmlkxYcmiC6ReansH5jAO5ZbAvcvy0PfUTw/nPylpsdYJkYyBA76Zr9hlvEFB1J1n54V2B 51F3r93YaJuUnQ2661rxuKo0mZLkJYEufkV40ZLnkYXkU1Sw096IYpxBPmGbHw== 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=1773137932; 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=+sPKo20/r4fsNFw/lfzGX7vZQSn+QH+HelMisTQzFnc=; b=PPn9itFXmWTG3IrmQmRwlQjRSE7u+hpFVD8Mygt9NAMtAGmeLI/N/Hym4EhDWFhgWKLDEP tL3Z2kh36R/EXiWM+zsMngWZ1pG0F7WvTTCeodL6w0MwxCS0ZIlypzqdLNnrsO39qcew2m Z6YyosGuu2F/mTUrfhzTOiFdX8RJc6t6SLCtIhNnRwc7RM/pH1uYGrZ3ocV1ZQg8edQi+U uRmcPwPpBtuyKD5RXwfU8VyLPftCc4UAOJu6R4aLBVYi+sI1ec6fjt1Rg/dZ5QjrxUGjHL veLD0yqD75aAmGbeR1Js61cPQ3QgsFXxYOWdCmbDH33r7kGxo87PmfW1Z6o1Ew== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fVVGM6x0Fz17Cg for ; Tue, 10 Mar 2026 10:18:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 43817 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 10 Mar 2026 10:18:51 +0000 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=B8rg?=rav Subject: git: cf74b63d61b4 - main - yes: Completely overengineer List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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: cf74b63d61b49db848ecc20b87e7ee5f16671320 Auto-Submitted: auto-generated Date: Tue, 10 Mar 2026 10:18:51 +0000 Message-Id: <69aff00b.43817.51bdaf7b@gitrepo.freebsd.org> The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=cf74b63d61b49db848ecc20b87e7ee5f16671320 commit cf74b63d61b49db848ecc20b87e7ee5f16671320 Author: Dag-Erling Smørgrav AuthorDate: 2026-03-10 10:18:08 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-03-10 10:18:08 +0000 yes: Completely overengineer If we're going to overengineer this, we may as well go all the way. * If multiple arguments are given, concatenate them into a space- separated list like GNU coreutils does. * When duplicating the expletive, do so exponentially. * Most importantly, don't modify the memory that argv points to. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: kevans, allanjude Differential Revision: https://reviews.freebsd.org/D55617 --- usr.bin/yes/yes.1 | 6 +++-- usr.bin/yes/yes.c | 75 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/usr.bin/yes/yes.1 b/usr.bin/yes/yes.1 index 8ed8beab0d28..689031345dc3 100644 --- a/usr.bin/yes/yes.1 +++ b/usr.bin/yes/yes.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 4, 2014 +.Dd March 2, 2026 .Dt YES 1 .Os .Sh NAME @@ -33,7 +33,7 @@ .Nd be repetitively affirmative .Sh SYNOPSIS .Nm -.Op Ar expletive +.Op Ar expletive ... .Sh DESCRIPTION The .Nm @@ -42,6 +42,8 @@ utility outputs or, by default, .Dq y , forever. +If multiple arguments are given, they are concatenated into a single +space-separated string. .Sh SEE ALSO .Xr jot 1 , .Xr seq 1 diff --git a/usr.bin/yes/yes.c b/usr.bin/yes/yes.c index d9e896b6ea27..53224603cf95 100644 --- a/usr.bin/yes/yes.c +++ b/usr.bin/yes/yes.c @@ -35,40 +35,71 @@ #include #include +/* + * Default expletive + */ +#define EXP "y\n" +#define EXPLEN strlen(EXP) + +/* + * Optimum and maximum buffer size. The optimum is just a little less + * than the default value of kern.ipc.pipe_mindirect; writing more than + * that is significantly slower, but we want to get as close as possible + * to minimize the number of system calls. The maximum is enough for a + * maximal command line plus a newline and terminating NUL. + */ +#define OPTBUF 8190 +#define MAXBUF (ARG_MAX + 2) + int main(int argc, char **argv) { - char buf[8192]; - char y[2] = { 'y', '\n' }; - char * exp = y; - size_t buflen = 0; - size_t explen = sizeof(y); - size_t more; - ssize_t ret; + static char buf[MAXBUF] = EXP; + char *end = buf + sizeof(buf), *exp, *pos = buf + EXPLEN; + size_t buflen, explen = EXPLEN; + ssize_t wlen = 0; if (caph_limit_stdio() < 0 || caph_enter() < 0) err(1, "capsicum"); - if (argc > 1) { - exp = argv[1]; - explen = strlen(exp) + 1; - exp[explen - 1] = '\n'; - } + argc -= 1; + argv += 1; - if (explen <= sizeof(buf)) { - while (buflen < sizeof(buf) - explen) { - memcpy(buf + buflen, exp, explen); - buflen += explen; + /* Assemble the expletive */ + if (argc > 0) { + /* Copy positional arguments into expletive buffer */ + for (pos = buf, end = buf + sizeof(buf); + argc > 0 && pos < end; argc--, argv++) { + /* Separate with spaces */ + if (pos > buf) + *pos++ = ' '; + exp = *argv; + while (*exp != '\0' && pos < end) + *pos++ = *exp++; } - exp = buf; - explen = buflen; + /* This should not be possible, but check anyway */ + if (pos > end - 2) + pos = end - 2; + *pos++ = '\n'; + explen = pos - buf; } - more = explen; - while ((ret = write(STDOUT_FILENO, exp + (explen - more), more)) > 0) - if ((more -= ret) == 0) - more = explen; + /* + * Double until we're past OPTBUF, then reduce buflen to exactly + * OPTBUF. It doesn't matter if that's not a multiple of explen; + * the modulo operation in the write loop will take care of that. + */ + for (buflen = explen; buflen < OPTBUF; pos += buflen, buflen += buflen) + memcpy(pos, buf, buflen); + if (explen < OPTBUF && buflen > OPTBUF) + buflen = OPTBUF; + /* Dump it to stdout */ + end = (pos = buf) + buflen; + do { + pos = buf + (pos - buf + wlen) % explen; + wlen = write(STDOUT_FILENO, pos, end - pos); + } while (wlen > 0); err(1, "stdout"); /*NOTREACHED*/ }