From nobody Tue Mar 10 10:18:51 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 4fVVGT1CRdz6VPBC for ; Tue, 10 Mar 2026 10:18:57 +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 4fVVGT0fc8z3vSX for ; Tue, 10 Mar 2026 10:18:57 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1773137937; 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=nv4AuIjIbJQsILMQadMfNMEC0Y/0tmjKVJ6fkHqwgbBiAkAlQ3YlmTFcbSkNX0do3YKVfE 92cvCdCmORFZFIzdMovF/lA2ouyxuIIjmLaAEW+JcPbKlsLOPn0MRmJ1Nzmo1YIv8L0B9K F8WuKIw2VOjj77+jrGpFozOncznK6waQHA24P9BbgfczHhYs0bKd0nOrxQrqkMot2nCvZ4 buYItA5uv6dg45ionjL6T/Jtnqu6M3gmo4oDTdtZesDVP8ghQlSPxo8Wx6Uc9L/RWZnh9+ LuX5LZK5F6vXkTeUQEYUJzG/LqvxWjVHZd9wwy05s8zWhyokYgLBHlCNUO7Odw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1773137937; a=rsa-sha256; cv=none; b=WnqzFB8UEpYBAqfGd6jgEhcmaRCw+jw18LEMqARHjddeG5Tk/x24Ybc5w6GeTwryy69v0b LVTHAB9GRMwOLV6eqEThI31SDESWyKtNVGdhWdQCY8ql2SxmzGsetylIaA2Cs/9QAM7L+f Wgql5WUtx9hmn5+2CEb5aPCFDeYp5UKDGBzLgRgqAwPZbIDSW33DCrmE/1DY9hR1yiCjHH na0YXqMpU/2ozmUcg3bU8aiNMuThu3jmtnZVCDC18rf02VOto0L+MwqAT/UZ97kZ7viQCU iesD3I1WJ4i1Z/1HHewckme/GFAjLqutZxl+hn+8I8O0XCEnTKaLchpg0F0SvA== 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=1773137937; 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=am52cdYkB57bm+mHeeYyBnBDcNEafD3gG5F+Gt/TW2/A8yopL6/MkNr6S4uGNzb8rgWjMo quPp7ItmAKQxq60aPWZYNns6oFUWp+Npa7SK/Vt4lVqwjgWMB0E6QIiF+k4xYbS4H5VifZ UV1Fnppj2C/qO1Q6IlQ/yDWv1uaUUVEuy4nDlCPn5hr8JTLvAb+5vJKtj3VQYoJ4XLRPQ5 CxwtdXBoZ94+5VQbjBrXS1CPN+lwg1VwAFDgmgJ4nrZIZCLVlN1FQ3VHVAeOZg5rXhUC51 7xu2qwq7RR+3eDovinrcw+GbS987bfM3mjnLWqBsLSoFymk7Tu/aRUU2+8e7jQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fVVGS72y7z16lK for ; Tue, 10 Mar 2026 10:18:56 +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 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: 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*/ }