logo

utils-std

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

cat.c (2633B)


  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 "../lib/fs.h"
  6. #include <errno.h>
  7. #include <fcntl.h> // open, O_RDONLY
  8. #include <limits.h> // SSIZE_MAX
  9. #include <stdio.h> // fprintf, BUFSIZ
  10. #include <stdlib.h> // abort
  11. #include <string.h> // strerror, strncmp
  12. #include <unistd.h> // read, write, close, getopt
  13. const char *argv0 = "cat";
  14. static void
  15. usage(void)
  16. {
  17. fprintf(stderr, "Usage: cat [-u] [files ...]\n");
  18. }
  19. int
  20. main(int argc, char *argv[])
  21. {
  22. for(int c = -1; (c = getopt(argc, argv, ":u")) != -1;)
  23. {
  24. switch(c)
  25. {
  26. case 'u':
  27. // POSIX: Ignored, buffered streams aren't used
  28. break;
  29. case ':':
  30. fprintf(stderr, "%s: error: Missing operand for option: '-%c'\n", argv0, optopt);
  31. usage();
  32. return 1;
  33. case '?':
  34. fprintf(stderr, "%s: error: Unrecognised option: '-%c'\n", argv0, optopt);
  35. usage();
  36. return 1;
  37. default:
  38. abort();
  39. }
  40. }
  41. argc -= optind;
  42. argv += optind;
  43. if(argc < 1)
  44. {
  45. if(auto_fd_copy(STDIN_FILENO, STDOUT_FILENO, SSIZE_MAX) < 0)
  46. {
  47. fprintf(stderr, "%s: error: Failed copying data from <stdin>: %s\n", argv0, strerror(errno));
  48. return 1;
  49. }
  50. }
  51. else
  52. {
  53. for(int argi = 0; argi < argc; argi++)
  54. {
  55. if(strncmp(argv[argi], "-", 2) == 0)
  56. {
  57. if(auto_fd_copy(STDIN_FILENO, STDOUT_FILENO, SSIZE_MAX) < 0)
  58. {
  59. fprintf(
  60. stderr, "%s: error: Failed copying data from <stdin>: %s\n", argv0, strerror(errno));
  61. return 1;
  62. }
  63. }
  64. else
  65. {
  66. int fd = open(argv[argi], O_RDONLY);
  67. if(fd < 0)
  68. {
  69. fprintf(stderr,
  70. "%s: error: Failed opening file '%s': %s\n",
  71. argv0,
  72. argv[argi],
  73. strerror(errno));
  74. errno = 0;
  75. return 1;
  76. }
  77. if(auto_fd_copy(fd, STDOUT_FILENO, SSIZE_MAX) < 0)
  78. {
  79. fprintf(stderr,
  80. "%s: error: Failed copying data from file '%s': %s\n",
  81. argv0,
  82. argv[argi],
  83. strerror(errno));
  84. return 1;
  85. }
  86. if(close(fd) < 0)
  87. {
  88. fprintf(stderr,
  89. "%s: error: Failed closing file '%s': %s\n",
  90. argv0,
  91. argv[argi],
  92. strerror(errno));
  93. errno = 0;
  94. return 1;
  95. }
  96. }
  97. }
  98. }
  99. if(close(STDIN_FILENO) != 0)
  100. {
  101. fprintf(stderr, "%s: error: Failed closing file <stdin>: %s\n", argv0, strerror(errno));
  102. return 1;
  103. }
  104. if(close(STDOUT_FILENO) != 0)
  105. {
  106. fprintf(stderr, "%s: error: Failed closing file <stdout>: %s\n", argv0, strerror(errno));
  107. return 1;
  108. }
  109. return 0;
  110. }