From 443c8b479d7ca0bf45f691ab2da6fb8d35045d1f Mon Sep 17 00:00:00 2001 From: zlg Date: Sat, 20 May 2017 01:13:28 -0700 Subject: Solve Exercise 8-1: `cat` remastered --- ch8/8-01_cat-remastered.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 ch8/8-01_cat-remastered.c (limited to 'ch8') 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 /* 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); +} -- cgit v1.2.3-54-g00ecf 24777143&follow=1'>vgstash: let backlog filter ignore unbeatable gameszlg1-1/+1 2018-10-18Bump to 0.3beta2 for PyPIzlg1-3/+3 2018-10-18vgstash.DB.__init__: fix error output formattingzlg1-1/+1 2018-10-18README: fix inline <code> formattingzlg1-3/+4 2018-10-18cli: show msg if game to be deleted is not in DBzlg2-2/+12 2018-10-18README: expand on usage, cover shell quotingzlg1-7/+99 2018-10-18cli: Tell the user when a game lacks noteszlg2-3/+15 2018-10-18Catch when an invalid list filter is passedzlg4-3/+24 2018-10-12cli: Add zero-game import/export messageszlg2-11/+18 2018-10-10Bump to 0.3beta1 for PyPIzlg1-1/+1 2018-10-10Move tests and data to dedicated directoryzlg7-10/+26 2018-10-10cli: Add "export" commandzlg2-5/+54 2018-10-10cli: Add "import" commandzlg5-1/+76 2018-10-09Bump to 0.3alpha6 for PyPIzlg1-1/+1 2018-10-09cli: Add "notes" commandzlg2-4/+74 2018-10-09update_game: ensure notes are also savedzlg1-2/+2 2018-10-09cli: add 'update' commandzlg3-20/+92 2018-10-06cli: Add "delete" commandzlg2-0/+19 2018-10-06Remove ID field from DBzlg3-38/+46 2018-10-06cli: change "Status" heading to "Progress"zlg2-36/+40 2018-09-29Bump to 0.3alpha5 for PyPIzlg1-1/+1 2018-09-29cli: Add pretty printing to 'list' commandzlg3-17/+107 2018-09-08setup.py: Bump to alpha4 for PyPIzlg1-1/+1 2018-09-08cli: add '--raw' option to list commandzlg2-9/+45 2018-09-08Add remaining filters to vgstash packagezlg1-2/+11 2018-09-04Update LICENSE to match setup.pyzlg1-80/+67 2018-09-03Branch off from master with pytest, tox, clickzlg16-778/+779 2018-03-18Flesh out filter types and ownership statuszlg3-82/+144 2018-03-18README.mdown: break line correctlyzlg1-1/+1 2018-03-18add 'playlog' list filterzlg2-2/+9 2018-03-13Update helpers a bitzlg1-2/+9 2018-03-13Make VGSTASH_DB_LOCATION point to a filezlg2-21/+20 2016-11-18Remove settings from helpers.shZe Libertine Gamer1-5/+0 2016-11-15Correct phrasing in README.Ze Libertine Gamer1-4/+4 2016-11-13DerpZe Libertine Gamer1-0/+1 2016-11-03Improve error handling in shell scriptsZe Libertine Gamer4-3/+23 2016-10-24Correct run_again, add recursionZe Libertine Gamer1-0/+4 2016-10-21Add quotes to correct behavior for arglistZe Libertine Gamer1-1/+1 2016-10-14updater.sh: add recursion, error handlingZe Libertine Gamer1-43/+101 2016-10-14Correct pipe-handling behaviorZe Libertine Gamer1-1/+9 2016-10-12Clarify a method to move between platformsZe Libertine Gamer1-2/+5