tee.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. /*
  3. * Copyright (C) 2022, 2023 Ferass El Hafidi <vitali64pmemail@protonmail.com>
  4. */
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <signal.h>
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <stdint.h>
  11. #include <string.h>
  12. /* Requirements in common.h */
  13. #define REQ_PRINT_USAGE
  14. #define REQ_ERRPRINT
  15. #include "../common/common.h"
  16. #define DESCRIPTION "Duplicate standard input."
  17. #define OPERANDS "[-ai] [file...]"
  18. int main(int argc, char *argv[]) {
  19. int argument, length, i = 0, fildes[13], append_or_truncate = O_TRUNC;
  20. int ret = 0; /* Used for write errors. */
  21. char *argv0 = strdup(argv[0]), buffer[4096];
  22. while ((argument = getopt(argc, argv, "ai")) != -1) {
  23. if (argument == '?')
  24. return print_usage(argv0, DESCRIPTION, OPERANDS, VERSION);
  25. else if (argument == 'i') {
  26. struct sigaction signal_action;
  27. signal_action.sa_handler = SIG_IGN;
  28. sigemptyset(&signal_action.sa_mask);
  29. sigaction(SIGINT, &signal_action, NULL);
  30. } else if (argument == 'a')
  31. append_or_truncate = O_APPEND;
  32. } argc -= optind; argv += optind;
  33. /* Open all files */
  34. for (i = 0; i < argc && argc != 0 && i <= 13; i++) { /* TODO: No file limit */
  35. fildes[i] = open(argv[i], O_WRONLY | O_CREAT | append_or_truncate, 0666);
  36. if (errno) return errprint(argv0, argv[i], errno);
  37. }
  38. while ((length = read(STDIN_FILENO, buffer, 4096)) > 0) {
  39. write(STDOUT_FILENO, buffer, length); /* Write to stdout. */
  40. /* ...And to all other files */
  41. for (i = 0; i < argc && argc != 0 && i <= 13; i++) {
  42. write(fildes[i], buffer, length);
  43. if (errno) ret = errprint(argv0, argv[i], length);
  44. }
  45. }
  46. for (i = 0; i < argc && argc != 0 && i <= 13; i++) {
  47. close(fildes[i]);
  48. if (errno) return errprint(argv0, argv[i], errno);
  49. }
  50. return ret;
  51. }