From nobody Mon Mar 23 15:08:20 2026 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 4ffc4T6cwYz6W7Gg for ; Mon, 23 Mar 2026 15:08:25 +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 4ffc4T3gzlz47KL for ; Mon, 23 Mar 2026 15:08:25 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1774278505; 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=uZofXd3OXvTppFHznaHBxo+EALDNK7IvQ5Gm1df0DZ8=; b=xIwf73hXohhu5aZ88SF7rK+xYdbJUPYYRentjmyZ/ZohQjyLIQ+cW7ClmtIeXxx4w8kpxg Sl2yXSOUvZAxua0K17O/ZfAXhmfkaYgnrvETuKVPa4ueUh7ClDRaxfSB+tba4dAyrIST8H 2O8vG59ni6zNZJlz5Gavd12FhyUhyYTnLTBrU7qqbW78Lf/zATwptF5Ek4UkhlBk5VXobV UAbV3Tboe+s/7ExK6SzBatsEseO6KT0zb15vPBCC80uWd2cNnQlwjrWAlYXauWoztqBK+Z ocvS8gNWa48dpVtcwxSznE3A/DarBtO2G07yAC6XE1kIPeepMUO6+BDp1xfKGA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1774278505; a=rsa-sha256; cv=none; b=Ub8T1X0mix2tNsYi9olp/1JZGwjSoVMtyoHFxiOS6CdiH+LGVbn3REtrIFc6vMQMn6Qakn jrLQRoMeejGS9RKeYO0630JTEbR2FvbS3XhAyoX8YQJATRqra3ZS2fAY7f8n6xL95A0uEY +1PyIqrCWVPY5QhAz9aAiejDqdgnOu7LCDkhsdAXTVB7Yy6Uz8hdvLO2YvZ2F3exBPoBrM ishJLkscjiPP4hCipGGOddTaOP0y3BRuLBUkdUARYElikw0ZLRCGLtdGEV900u8IDEhAi0 eclUt4EHjG8lceq6HSqHL3ijX1x3NRwXiQlleNj2jQ5RyBOtTdjXZUbtsFs8Sg== 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=1774278505; 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=uZofXd3OXvTppFHznaHBxo+EALDNK7IvQ5Gm1df0DZ8=; b=xpwwI5pM7h3Ynw8Zmk65C7v3qWGKEA11FYmGPwLmBNNr8VDzd8whwh+UkBvB0td5kz5nwb RLs85aRBT7pWK7Ec/JrNMg5nozKy2aqRM1yCAVzUtLGPkWGYl3lQfgPdja+rcXNcul6byq kAnYLDwzhXS2dw03STNAY6r0GFR2ecGMYApaLt3xs7CLQY2g53lZtkPNilgv7AeFxJ5ymt +5CerY32Uh/QnCANXAgntzj81uOkguOLdsJ3gsjntG1+FkH1gs5ShyJTva8cGuet24hCyQ ndSbbt2hnneU7sGZvGCrROL6QMQDdbgd2b/ZiaoqFPR/LM+CTBGGm1ZCRzVQKw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4ffc4T2wQ3zsvj for ; Mon, 23 Mar 2026 15:08:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1dc64 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 23 Mar 2026 15:08:20 +0000 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=B8rg?=rav Subject: git: f2e600ff156d - stable/15 - yes: Completely overengineer 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/15 X-Git-Reftype: branch X-Git-Commit: f2e600ff156d6ac80630b199c3781ac3c1527a9c Auto-Submitted: auto-generated Date: Mon, 23 Mar 2026 15:08:20 +0000 Message-Id: <69c15764.1dc64.13379aa0@gitrepo.freebsd.org> The branch stable/15 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=f2e600ff156d6ac80630b199c3781ac3c1527a9c commit f2e600ff156d6ac80630b199c3781ac3c1527a9c Author: Dag-Erling Smørgrav AuthorDate: 2026-03-10 10:18:08 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-03-22 17:32:39 +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 (cherry picked from commit cf74b63d61b49db848ecc20b87e7ee5f16671320) yes: Add missing header This is a no-op on FreeBSD due to namespace pollution. MFC after: 1 week Sponsored by: Klara, Inc. Fixes: cf74b63d61b4 ("yes: Completely overengineer") (cherry picked from commit ba7439f0a9604b15bfef8084816f34d55eb6bdf2) --- usr.bin/yes/yes.1 | 6 +++-- usr.bin/yes/yes.c | 76 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 58 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..86022c82f453 100644 --- a/usr.bin/yes/yes.c +++ b/usr.bin/yes/yes.c @@ -31,44 +31,76 @@ #include #include +#include #include #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*/ }