From c8d6e9f5e4140cb6fcfad66748125e6dc6c0e7a8 Mon Sep 17 00:00:00 2001 From: emma Date: Mon, 7 Aug 2023 20:38:57 -0600 Subject: [PATCH] cat(1p): fix unbuffered output --- src/cat.c | 42 ++++++++++++------------------ trincat.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 26 deletions(-) create mode 100644 trincat.c diff --git a/src/cat.c b/src/cat.c index 1807acf..250170d 100644 --- a/src/cat.c +++ b/src/cat.c @@ -28,9 +28,9 @@ #include int main(int argc, char *argv[]) { - int i = 1; bool u = false; - + int opt; + FILE *file; char *usage_text = "(-u) [file...]"; int buf_size = strlen(argv[0]) + strlen("Usage: ") + strlen(usage_text) + 3; char *usage = calloc(buf_size, buf_size); @@ -39,8 +39,7 @@ int main(int argc, char *argv[]) { snprintf(usage, buf_size, "Usage: %s (-u) [file...]\n", argv[0]) ) < 0 ) {} - int opt; - + extern int optind; while ((opt = getopt(argc, argv, "u")) != -1) { switch(opt) { /* @@ -50,17 +49,17 @@ int main(int argc, char *argv[]) { * without delay as each is read. */ case 'u': - i = 2; u = true; break; default: break; } } + argv += optind; + argc -= optind; - FILE *file; - - for (; i <= (argc - 1); i++) { + for (int i = 0; i < argc; i++) { + int byte = 0; /* * From cat(1p): * @@ -72,33 +71,24 @@ int main(int argc, char *argv[]) { * but shall accept multiple occurrences of '-' as a file * operand. */ - printf("argv[%d]: %s\n", i, argv[i]); - if (argv[i] == "-" || u && (argc - 1) == 1 || !u && argc == 1) { - file = fdopen(0, "r"); + if (argv[i] == "-" || argc == 0) { + file = stdin; } else if ((file = fopen(argv[i], "r")) == NULL) { // TODO: Add error handling fputs(usage, stderr); return EX_NOINPUT; } - int byte = 0; - - if (u) { - while (byte != EOF) { - byte = fgetc(file); + for (char *buf = calloc(4096, 1); byte != EOF; fputs(buf, stdout)) { + byte = fgetc(file); + if (u) { putchar(byte); - } - } else { - char *buf = calloc(1, 4096); - while (byte != EOF) { - byte = fgetc(file); - fputc(byte, fdopen(1, "r")); + } else { + snprintf(buf, 4096, "%c", byte); } } - if (fclose(file) == -1) { - fprintf(stderr, "%s: %s: Error closing file.\n", argv[0], argv[i]); - return EX_OSERR; - } + + if (file != stdin) { fclose(file); } } return EX_OK; diff --git a/trincat.c b/trincat.c new file mode 100644 index 0000000..7a3e389 --- /dev/null +++ b/trincat.c @@ -0,0 +1,78 @@ +#include /* maybe */ +#include /* no */ +#include /* sure */ +#include /* no */ +#include /* yes */ +#include /* yes */ +#include /* maybe */ +#include /* yes */ +#define BUF_SIZE 4096 + +unsigned char u = 0; /* unbuffered */ +unsigned char buf[BUF_SIZE]; + +void usage(char *argv0){ + fprintf(stderr, "Usage: %s (-u) (file...)\n", argv0); + exit(EX_USAGE); +} + +int main(int argc, char *argv[]) { + char *argv0; + extern int optind; + int c; + FILE *in; + argv0 = argv[0]; + + while ((c = getopt(argc, argv, "u")) != -1) { + switch(c) { + /* + * From cat(1p): + * + * -u Write bytes from the input file to the standard output + * without delay as each is read. + */ + case 'u': + u = 1; + break; + default: + usage(argv[0]); + } + } + + while(++argv != NULL) /* increments over argv[0] */ + /* + * From cat(1p): + * + * file A pathname of an input file. If no file operands are + * specified, the standard input shall be used. If a file is + * '-', the cat utility shall read from the standard input at + * that point in the sequence. The cat utility shall not close + * and reopen standard input when it is referenced in this way, + * but shall accept multiple occurrences of '-' as a file + * operand. + */ + if(argv[0][0] == '-' && argv[0][1] == '\0') in = stdin; + else if ((in = fopen(argv[0], "r")) == NULL) { + // TODO: Add error handling + usage(argv0); + return EX_NOINPUT; + } + + int byte = 0; + char *buf = calloc(4096, 1); + + while ((c = fgetc(in) != EOF)) { + if (u) { + putchar(c); + } else { + /* fucky wucky buffering */ + } + } + + if(!u) fputs(buf, stdout); + + if(in != stdin) fclose(file); /* who cares if it cant close */ + } + + return EX_OK; + }