diff options
author | zlg <zlg@zlg.space> | 2017-05-20 01:13:28 -0700 |
---|---|---|
committer | zlg <zlg@zlg.space> | 2017-05-20 01:13:28 -0700 |
commit | 443c8b479d7ca0bf45f691ab2da6fb8d35045d1f (patch) | |
tree | c3fe6c39af9192baabb29501fedb35975f57732c | |
parent | Solve Exercise 7-9: isupper, time, and space (diff) | |
download | knr-443c8b479d7ca0bf45f691ab2da6fb8d35045d1f.tar.gz knr-443c8b479d7ca0bf45f691ab2da6fb8d35045d1f.tar.bz2 knr-443c8b479d7ca0bf45f691ab2da6fb8d35045d1f.tar.xz knr-443c8b479d7ca0bf45f691ab2da6fb8d35045d1f.zip |
Solve Exercise 8-1: `cat` remastered
-rw-r--r-- | ch8/8-01_cat-remastered.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/ch8/8-01_cat-remastered.c b/ch8/8-01_cat-remastered.c new file mode 100644 index 0000000..5e11ca8 --- /dev/null +++ b/ch8/8-01_cat-remastered.c @@ -0,0 +1,115 @@ +#include <stdio.h> /* printf and friends */ +#include <fcntl.h> /* open, creat, etc */ +#include <unistd.h> /* read, close */ +#include <stdarg.h> /* va_* */ +#include <stdlib.h> /* 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); +} |