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
This commit is contained in:
+4
-2
@@ -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
|
||||
|
||||
+53
-22
@@ -35,40 +35,71 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* 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*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user