yes.c (1750B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include <assert.h>
- #include <errno.h>
- #include <limits.h> // PAGESIZE
- #include <stdio.h> // perror
- #include <string.h> // strlen
- #include <unistd.h> // write
- #ifndef PAGESIZE
- // When undefined (allowed by POSIX), assume a somewhat modern system but not too modern
- #define PAGESIZE 4096
- // If getting a true pagesize is important then sysconf(_SC_PAGESIZE)
- // should be used as it is more runtime than ABI.
- // (for example AArch64 allows different pagesizes)
- #endif
- int
- main(int argc, char *argv[])
- {
- char *args = NULL;
- size_t args_len = 0;
- if(argc == 1)
- {
- static char str_yes[3] = {'y', '\n', '\0'};
- args = str_yes;
- args_len = 2;
- }
- else
- {
- argv++;
- argc--;
- args = *argv;
- for(int i = 0; i < argc; i++)
- {
- size_t len = strlen(argv[i]);
- argv[i][len] = ' ';
- args_len += len + 1; // str + space
- }
- if(args_len == 0)
- {
- static char str_nl[2] = {'\n', '\0'};
- args = str_nl;
- args_len = 1;
- }
- else
- argv[0][args_len - 1] = '\n';
- }
- size_t buflen = args_len;
- char *buf = args;
- // Large buffer to avoid write-speed being syscall-bound
- // PAGESIZE was chosen because yes(1) is likely going to be piped
- if(args_len < PAGESIZE)
- {
- static char page_buf[PAGESIZE] = "";
- buf = page_buf;
- size_t i = 0;
- do
- {
- memcpy(buf + i, args, args_len);
- i += args_len;
- } while(i < (PAGESIZE - args_len));
- buflen = i;
- }
- assert(errno == 0);
- while(write(STDOUT_FILENO, buf, buflen) >= 1)
- ;
- if(errno != 0)
- {
- perror("yes: error: Failed writing");
- return 1;
- }
- return 0;
- }