/* cat - concatenates files Author: Andy Tanenbaum */ /* 30 March 1990 - Slightly modified for efficiency by Norbert Schlenker. */ /* 23 March 2002 - Proper error messages by Kees J. Bot. */ #include #include #include #include #include #include #include #include #define CHUNK_SIZE (2048 * sizeof(char *)) static int unbuffered; static char ibuf[CHUNK_SIZE]; static char obuf[CHUNK_SIZE]; static char *op = obuf; int main(int argc, char **argv); static void copyout(char *file, int fd); static void output(char *buf, size_t count); static void report(char *label); static void fatal(char *label); static char STDIN[] = "standard input"; static char STDOUT[] = "standard output"; static int excode = 0; int main(int argc, char *argv[]) { int i, fd; i = 1; while (i < argc && argv[i][0] == '-') { char *opt = argv[i] + 1; if (opt[0] == 0) break; /* - */ i++; if (opt[0] == '-' && opt[1] == 0) break; /* -- */ while (*opt != 0) switch (*opt++) { case 'u': unbuffered = 1; break; default: std_err("Usage: cat [-u] [file ...]\n"); exit(1); } } if (i >= argc) { copyout(STDIN, STDIN_FILENO); } else { while (i < argc) { char *file = argv[i++]; if (file[0] == '-' && file[1] == 0) { copyout(STDIN, STDIN_FILENO); } else { fd = open(file, O_RDONLY); if (fd < 0) { report(file); } else { copyout(file, fd); close(fd); } } } } output(obuf, (op - obuf)); return(excode); } static void copyout(char *file, int fd) { int n; while (1) { n = read(fd, ibuf, CHUNK_SIZE); if (n < 0) fatal(file); if (n == 0) return; if (unbuffered || (op == obuf && n == CHUNK_SIZE)) { output(ibuf, n); } else { int bytes_left; bytes_left = &obuf[CHUNK_SIZE] - op; if (n <= bytes_left) { memcpy(op, ibuf, (size_t)n); op += n; } else { memcpy(op, ibuf, (size_t)bytes_left); output(obuf, CHUNK_SIZE); n -= bytes_left; memcpy(obuf, ibuf + bytes_left, (size_t)n); op = obuf + n; } } } } static void output(char *buf, size_t count) { ssize_t n; while (count > 0) { n = write(STDOUT_FILENO, buf, count); if (n <= 0) { if (n < 0) fatal(STDOUT); std_err("cat: standard output: EOF\n"); exit(1); } buf += n; count -= n; } } static void report(char *label) { int e = errno; std_err("cat: "); std_err(label); std_err(": "); std_err(strerror(e)); std_err("\n"); excode = 1; } static void fatal(char *label) { report(label); exit(1); }