logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git

yes.c (1750B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include <assert.h>
  6. #include <errno.h>
  7. #include <limits.h> // PAGESIZE
  8. #include <stdio.h> // perror
  9. #include <string.h> // strlen
  10. #include <unistd.h> // write
  11. #ifndef PAGESIZE
  12. // When undefined (allowed by POSIX), assume a somewhat modern system but not too modern
  13. #define PAGESIZE 4096
  14. // If getting a true pagesize is important then sysconf(_SC_PAGESIZE)
  15. // should be used as it is more runtime than ABI.
  16. // (for example AArch64 allows different pagesizes)
  17. #endif
  18. int
  19. main(int argc, char *argv[])
  20. {
  21. char *args = NULL;
  22. size_t args_len = 0;
  23. if(argc == 1)
  24. {
  25. static char str_yes[3] = {'y', '\n', '\0'};
  26. args = str_yes;
  27. args_len = 2;
  28. }
  29. else
  30. {
  31. argv++;
  32. argc--;
  33. args = *argv;
  34. for(int i = 0; i < argc; i++)
  35. {
  36. size_t len = strlen(argv[i]);
  37. argv[i][len] = ' ';
  38. args_len += len + 1; // str + space
  39. }
  40. if(args_len == 0)
  41. {
  42. static char str_nl[2] = {'\n', '\0'};
  43. args = str_nl;
  44. args_len = 1;
  45. }
  46. else
  47. argv[0][args_len - 1] = '\n';
  48. }
  49. size_t buflen = args_len;
  50. char *buf = args;
  51. // Large buffer to avoid write-speed being syscall-bound
  52. // PAGESIZE was chosen because yes(1) is likely going to be piped
  53. if(args_len < PAGESIZE)
  54. {
  55. static char page_buf[PAGESIZE] = "";
  56. buf = page_buf;
  57. size_t i = 0;
  58. do
  59. {
  60. memcpy(buf + i, args, args_len);
  61. i += args_len;
  62. } while(i < (PAGESIZE - args_len));
  63. buflen = i;
  64. }
  65. assert(errno == 0);
  66. while(write(STDOUT_FILENO, buf, buflen) >= 1)
  67. ;
  68. if(errno != 0)
  69. {
  70. perror("yes: error: Failed writing");
  71. return 1;
  72. }
  73. return 0;
  74. }