#include /* printf and friends */ #include /* open, creat, etc */ #include /* read, close */ #include /* va_* */ #include /* exit */ /* The C Programming Language: 2nd Edition * * Exercise 8-1: Rewrite the program `cat` from Chapter 7 using read(), * write(), open(), and close() instead of their standard library * equivalents. Perferm experiments to determine the relative speeds of * the two versions. * * Notes: The `cat` program can be found on pp 162-163 in the book. */ #define DEBUG 0 char buf; /* Let's have fewer magic numbers */ enum { STDIN, STDOUT, STDERR }; #if DEBUG == 1 /* d_printf - output a debug message * This was shamelessly taken from the book */ void d_printf(char *fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "debug: "); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); } #endif void in2out() { int status; while ((status = read(STDIN, &buf, 1))) { if (status != -1) { status = write(STDOUT, &buf, 1); if (status == -1) { fprintf(stderr, "error: Could not write to stdout; something is very wrong.\n"); exit(1); } } else { fprintf(stderr, "error: Could not read stdin; something is very wrong.\n"); } } } int main(int argc, char **argv) { int fd; /* Remember the name we were invoked as, for messages */ ssize_t fstatus; argv++; #if DEBUG == 1 char *prog = *argv; d_printf("Starting %s", prog); #endif if (argc == 1) { #if DEBUG == 1 d_printf("No arguments specified; copying stdin to stdout"); #endif in2out(); argv++; exit(0); } /* The trick to understanding this is "x--" will run one more time than * expected, because it doesn't decrement until after it's been evaluated * for use in the expression. You can also look at it as "we've already * pushed argv ahead by one". */ while (argc-- > 1) { #if DEBUG == 1 d_printf("Trying to open %s", *argv); #endif fd = open(*argv, O_RDONLY, 0); if (fd != -1) { #if DEBUG == 1 d_printf("It was successfully opened. Reading."); #endif while ((fstatus = read(fd, &buf, 1))) { if (fstatus == (-1)) { /* Fail early, fail often */ fprintf(stderr, "error: Cannot read from '%s'. \n", *argv); close(fd); return 1; } if ((fstatus = write(STDOUT, &buf, 1)) == (-1)) { fprintf(stderr, "error: Cannot write to stdout.\n"); close(fd); return 1; } } #if DEBUG == 1 d_printf("%s read complete.", *argv); #endif } else { fprintf(stderr, "error: Could not open file '%s' for reading.\n", *argv); close(fd); return 1; } #if DEBUG == 1 d_printf("Closing file %s.", *argv); #endif close(fd); argv++; } exit(0); }