logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git

echo.c (1350B)


  1. // Collection of Unix tools, comparable to coreutils
  2. // SPDX-FileCopyrightText: 2017-2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include <stdbool.h> /* bool */
  6. #include <stdio.h> /* perror */
  7. #include <stdlib.h> /* malloc */
  8. #include <string.h> /* strlen */
  9. #include <unistd.h> /* write */
  10. int
  11. main(int argc, char *argv[])
  12. {
  13. size_t arg_len = 0;
  14. char *buffer, *buffer_p;
  15. int err = 0;
  16. bool opt_n = false;
  17. if((argc >= 2) && (strncmp(argv[1], "-n", 3) == 0))
  18. {
  19. opt_n = true;
  20. argc--;
  21. argv++;
  22. }
  23. for(int i = 1; i < argc; i++)
  24. {
  25. arg_len += strlen(argv[i]) + 1; // str + space|newline
  26. }
  27. if(arg_len == 0)
  28. {
  29. if(opt_n) return 0;
  30. if(write(1, "\n", 1) < 1)
  31. {
  32. perror("echo: write(1, \"\n\", 1)");
  33. return 1;
  34. }
  35. return 0;
  36. }
  37. if(opt_n) arg_len--; // no newline
  38. buffer = malloc(arg_len);
  39. if(buffer == NULL)
  40. {
  41. perror("echo: malloc(arg_len)");
  42. return 1;
  43. }
  44. buffer_p = buffer;
  45. for(int i = 1; i < argc; i++)
  46. {
  47. size_t len = strlen(argv[i]);
  48. memcpy(buffer_p, argv[i], len);
  49. buffer_p += len;
  50. if(i < argc - 1)
  51. {
  52. *buffer_p++ = ' ';
  53. }
  54. }
  55. if(!opt_n) *buffer_p++ = '\n';
  56. if(write(1, buffer, arg_len) < (ssize_t)arg_len)
  57. {
  58. perror("echo: write(1, buffer, arg_len)");
  59. err++;
  60. }
  61. free(buffer);
  62. return err;
  63. }