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
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd June 4, 2014
|
.Dd March 2, 2026
|
||||||
.Dt YES 1
|
.Dt YES 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
.Nd be repetitively affirmative
|
.Nd be repetitively affirmative
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Ar expletive
|
.Op Ar expletive ...
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
@@ -42,6 +42,8 @@ utility outputs
|
|||||||
or, by default,
|
or, by default,
|
||||||
.Dq y ,
|
.Dq y ,
|
||||||
forever.
|
forever.
|
||||||
|
If multiple arguments are given, they are concatenated into a single
|
||||||
|
space-separated string.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr jot 1 ,
|
.Xr jot 1 ,
|
||||||
.Xr seq 1
|
.Xr seq 1
|
||||||
|
|||||||
+55
-24
@@ -35,40 +35,71 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[8192];
|
static char buf[MAXBUF] = EXP;
|
||||||
char y[2] = { 'y', '\n' };
|
char *end = buf + sizeof(buf), *exp, *pos = buf + EXPLEN;
|
||||||
char * exp = y;
|
size_t buflen, explen = EXPLEN;
|
||||||
size_t buflen = 0;
|
ssize_t wlen = 0;
|
||||||
size_t explen = sizeof(y);
|
|
||||||
size_t more;
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
if (caph_limit_stdio() < 0 || caph_enter() < 0)
|
if (caph_limit_stdio() < 0 || caph_enter() < 0)
|
||||||
err(1, "capsicum");
|
err(1, "capsicum");
|
||||||
|
|
||||||
if (argc > 1) {
|
argc -= 1;
|
||||||
exp = argv[1];
|
argv += 1;
|
||||||
explen = strlen(exp) + 1;
|
|
||||||
exp[explen - 1] = '\n';
|
/* 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++;
|
||||||
|
}
|
||||||
|
/* This should not be possible, but check anyway */
|
||||||
|
if (pos > end - 2)
|
||||||
|
pos = end - 2;
|
||||||
|
*pos++ = '\n';
|
||||||
|
explen = pos - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (explen <= sizeof(buf)) {
|
/*
|
||||||
while (buflen < sizeof(buf) - explen) {
|
* Double until we're past OPTBUF, then reduce buflen to exactly
|
||||||
memcpy(buf + buflen, exp, explen);
|
* OPTBUF. It doesn't matter if that's not a multiple of explen;
|
||||||
buflen += explen;
|
* the modulo operation in the write loop will take care of that.
|
||||||
}
|
*/
|
||||||
exp = buf;
|
for (buflen = explen; buflen < OPTBUF; pos += buflen, buflen += buflen)
|
||||||
explen = buflen;
|
memcpy(pos, buf, buflen);
|
||||||
}
|
if (explen < OPTBUF && buflen > OPTBUF)
|
||||||
|
buflen = OPTBUF;
|
||||||
more = explen;
|
|
||||||
while ((ret = write(STDOUT_FILENO, exp + (explen - more), more)) > 0)
|
|
||||||
if ((more -= ret) == 0)
|
|
||||||
more = explen;
|
|
||||||
|
|
||||||
|
/* 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");
|
err(1, "stdout");
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user