logo

utils-std

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

yes.c (1708B)


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