cat.c (2703B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include "../lib/fs.h"
- #include <assert.h>
- #include <errno.h>
- #include <fcntl.h> // open, O_RDONLY
- #include <limits.h> // SSIZE_MAX
- #include <stdio.h> // fprintf, BUFSIZ
- #include <stdlib.h> // abort
- #include <string.h> // strerror, strncmp
- #include <unistd.h> // read, write, close, getopt
- const char *argv0 = "cat";
- static void
- usage(void)
- {
- fprintf(stderr, "Usage: cat [-u] [files ...]\n");
- }
- int
- main(int argc, char *argv[])
- {
- int c = -1;
- while((c = getopt(argc, argv, ":u")) != -1)
- {
- switch(c)
- {
- case 'u':
- // POSIX: Ignored, buffered streams aren't used
- break;
- case ':':
- fprintf(stderr, "%s: error: Missing operand for option: '-%c'\n", argv0, optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "%s: error: Unrecognised option: '-%c'\n", argv0, optopt);
- usage();
- return 1;
- default:
- abort();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc < 1)
- {
- if(auto_fd_copy(STDIN_FILENO, STDOUT_FILENO, SSIZE_MAX) < 0)
- {
- fprintf(stderr, "%s: error: Failed copying data from <stdin>: %s\n", argv0, strerror(errno));
- return 1;
- }
- }
- else
- {
- for(int argi = 0; argi < argc; argi++)
- {
- if(strncmp(argv[argi], "-", 2) == 0)
- {
- if(auto_fd_copy(STDIN_FILENO, STDOUT_FILENO, SSIZE_MAX) < 0)
- {
- fprintf(
- stderr, "%s: error: Failed copying data from <stdin>: %s\n", argv0, strerror(errno));
- return 1;
- }
- }
- else
- {
- assert(errno == 0);
- int fd = open(argv[argi], O_RDONLY);
- if(fd < 0)
- {
- fprintf(stderr,
- "%s: error: Failed opening file '%s': %s\n",
- argv0,
- argv[argi],
- strerror(errno));
- errno = 0;
- return 1;
- }
- if(auto_fd_copy(fd, STDOUT_FILENO, SSIZE_MAX) < 0)
- {
- fprintf(stderr,
- "%s: error: Failed copying data from file '%s': %s\n",
- argv0,
- argv[argi],
- strerror(errno));
- return 1;
- }
- assert(errno == 0);
- if(close(fd) < 0)
- {
- fprintf(stderr,
- "%s: error: Failed closing file '%s': %s\n",
- argv0,
- argv[argi],
- strerror(errno));
- errno = 0;
- return 1;
- }
- }
- }
- }
- if(close(STDIN_FILENO) != 0)
- {
- fprintf(stderr, "%s: error: Failed closing file <stdin>: %s\n", argv0, strerror(errno));
- return 1;
- }
- if(close(STDOUT_FILENO) != 0)
- {
- fprintf(stderr, "%s: error: Failed closing file <stdout>: %s\n", argv0, strerror(errno));
- return 1;
- }
- return 0;
- }