From 2f69a2a3dbf2174935e8157d375f7315fd350caf Mon Sep 17 00:00:00 2001 From: gdr Date: Mon, 9 Sep 1996 06:12:16 +0000 Subject: [PATCH] Fixed buffered output: full buffering was being done rather than line buffering. Added program 'testtee' to provide output for testing. --- bin/tee/README | 5 ++- bin/tee/makefile.mk | 9 ++++- bin/tee/tee.1 | 6 +-- bin/tee/tee.DESCRIBE | 2 +- bin/tee/tee.c | 93 +++++++++++++++++++------------------------- bin/tee/testtee.c | 31 +++++++++++++++ 6 files changed, 85 insertions(+), 61 deletions(-) create mode 100644 bin/tee/testtee.c diff --git a/bin/tee/README b/bin/tee/README index b11f138..b9e0ba1 100644 --- a/bin/tee/README +++ b/bin/tee/README @@ -15,7 +15,7 @@ copyright 1987-1994 by Byte Works, Inc. Used with Permission. Devin Reade -$Id: README,v 1.2 1996/09/03 03:56:05 gdr Exp $ +$Id: README,v 1.3 1996/09/09 06:12:14 gdr Exp $ Change Log ========== @@ -26,4 +26,5 @@ v1.1 Rewrite from scratch by Devin Reade. Default changed from full buffering to no buffering. Added options for multiple output files, appending and ignoring of SIGINT. -v1.2 Added -b (line buffering) option. +v1.2 Added -b (line buffering) option. STDIN_FILENO is no longer + directly read; stdio is used. diff --git a/bin/tee/makefile.mk b/bin/tee/makefile.mk index e0014ad..4c49132 100644 --- a/bin/tee/makefile.mk +++ b/bin/tee/makefile.mk @@ -1,7 +1,7 @@ # # This makefile is intended for use with dmake(1) # -# $Id: makefile.mk,v 1.2 1996/09/03 03:56:06 gdr Exp $ +# $Id: makefile.mk,v 1.3 1996/09/09 06:12:15 gdr Exp $ # INSTALL = /usr/bin/install @@ -17,13 +17,18 @@ CFLAGS = -w -i -O -s768 $(DEFINES) LDFLAGS = -l/usr/lib/gnulib -s768 tee: tee.o tee.r + @purge $(CC) $(LDFLAGS) tee.o $(LDLIBS) -o $@ copyfork tee.r tee -r +testtee: testtee.c + @purge + $(CC) -v -w $< -o $@ + install: $(INSTALL) -m755 -obin -gsys -d $(BINDIR) $(MANDIR) $(INSTALL) -m755 -obin -gsys tee $(BINDIR) $(INSTALL) -m644 -obin -gsys tee.1 $(MANDIR) clean clobber: - $(RM) tee.r tee.o tee.root + $(RM) -f tee.r tee.o tee.root testtee testtee.o testtee.root diff --git a/bin/tee/tee.1 b/bin/tee/tee.1 index 57c349a..f28254e 100644 --- a/bin/tee/tee.1 +++ b/bin/tee/tee.1 @@ -1,7 +1,7 @@ -.\" $Id: tee.1,v 1.2 1996/09/03 03:56:06 gdr Exp $ +.\" $Id: tee.1,v 1.3 1996/09/09 06:12:15 gdr Exp $ .\" -.\" .TH TEE 1 "2 September 1996" "Version 1.2" "Commands and Applications" -.TH TEE 1 "Commands and Applications" "2 September 1996" "Version 1.2" +.\" .TH TEE 1 "8 September 1996" "Version 1.2" "Commands and Applications" +.TH TEE 1 "Commands and Applications" "8 September 1996" "Version 1.2" .SH NAME tee \- Pipe fitting. .SH SYNOPSIS diff --git a/bin/tee/tee.DESCRIBE b/bin/tee/tee.DESCRIBE index b940614..62d1256 100644 --- a/bin/tee/tee.DESCRIBE +++ b/bin/tee/tee.DESCRIBE @@ -1,5 +1,5 @@ Name: tee -Version: 1.2 (2 Sep 96) +Version: 1.2 (8 Sep 96) Author: Devin Reade Contact: Where: /bin/tee diff --git a/bin/tee/tee.c b/bin/tee/tee.c index 754aeb4..c247fe9 100644 --- a/bin/tee/tee.c +++ b/bin/tee/tee.c @@ -4,10 +4,11 @@ * Version 1.1 and later by Devin Reade * * tee originally appeared with Gno v1.x, but was fully buffered. - * This is a complete re-write which uses full buffering for the - * output file, but _no_ buffering on stdin and stdout. + * This is a complete re-write which by default uses full buffering + * for the output file, but _no_ buffering on stdin and stdout. + * This buffering behavior can be changed slightly by the -b flag. * - * $Id: tee.c,v 1.2 1996/09/03 03:56:07 gdr Exp $ + * $Id: tee.c,v 1.3 1996/09/09 06:12:16 gdr Exp $ */ #include @@ -50,17 +51,19 @@ int main(int argc, char **argv) { int c, b_flag; - char *mode, buf; + char *mode; FILE *fp, *fp2; + int characters; + extern int optind; - + /* * initialization */ STACKSTART; mode = "w+"; b_flag = 0; - + /* * parse the command line */ @@ -70,17 +73,17 @@ main(int argc, char **argv) /* append to instead of truncate output file */ mode = "a+"; break; - + case 'b': /* do line buffering */ b_flag++; break; - + case 'i': /* ignore SIGINT */ signal(SIGINT, SIG_IGN); break; - + case 'V': /* FALLTHROUGH */ default: @@ -91,6 +94,7 @@ main(int argc, char **argv) if ((argc - optind) < 1) { USAGE; } + /* * open the output file */ @@ -98,48 +102,29 @@ main(int argc, char **argv) perror("opening master file"); STACKEND(1); } + /* * loop until done with the first file */ if (b_flag) { /* line buffering */ - int done = 0; - - while (!done) { - c = fread(buf2, sizeof(char), BUFFERSIZE, stdin); - - if (c == 0) { - if (ferror(stdin)) { - fclose(fp); - STACKEND(1); - /* NOTREACHED */ - } - done = 1; - } - fwrite(buf2, sizeof(char), c, stdout); - fwrite(buf2, sizeof(char), c, fp); - } + setvbuf(stdin, NULL, _IOLBF, 1024); + setvbuf(stdout, NULL, _IOLBF, 1024); + characters = BUFFERSIZE; } else { /* no buffering */ - int done = 0; - - while (!done) { - switch (read(STDIN_FILENO, &buf, 1)) { - case -1: - fclose(fp); - STACKEND(1); - /* NOTREACHED */ - case 0: - done = 1; - break; - default: - write(STDOUT_FILENO, &buf, 1); - fputc(buf, fp); - break; - } - } + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + characters = 2; /* a value of 2 gives one character reads */ } + /* poll until EOF seen on input or an error occurs */ + while (fgets(buf2, characters, stdin) != NULL && + fputs(buf2, stdout) != EOF && + fputs(buf2, fp) != EOF); + fflush(fp); + fflush(stdout); + /* * make additional copies if necessary */ @@ -150,31 +135,33 @@ main(int argc, char **argv) } while (argc > optind) { size_t count; - + /* rewind the master file */ rewind(fp); - + /* open the new file */ if ((fp2 = fopen(argv[optind], mode)) == NULL) { perror("opening duplicate file"); fclose(fp); STACKEND(1); } + /* make the copy */ while (!feof(fp) && !(ferror(fp))) { count = fread(buf2, sizeof(char), BUFFERSIZE, fp); - + if (count > 0) { - fwrite(buf2, sizeof(char), count, fp2); - - if (ferror(fp2)) { - perror("writing duplicate file"); - fclose(fp); - fclose(fp2); - STACKEND(1); - } + fwrite(buf2, sizeof(char), count, fp2); + + if (ferror(fp2)) { + perror("writing duplicate file"); + fclose(fp); + fclose(fp2); + STACKEND(1); + } } } + fclose(fp2); if (ferror(fp)) { perror("reading master file"); diff --git a/bin/tee/testtee.c b/bin/tee/testtee.c new file mode 100644 index 0000000..d4f1dac --- /dev/null +++ b/bin/tee/testtee.c @@ -0,0 +1,31 @@ +/* + * This is a test for tee(1) buffering. It prints out LINES lines + * of DIGITS digits each, sleeping for SLEEP seconds between digits. + * + * Usage: ./testtee | ./tee [-b] + * + * $Id: testtee.c,v 1.1 1996/09/09 06:12:16 gdr Exp $ + */ + +#include +#include + +#define LINES 3 /* number of lines to print */ +#define DIGITS 4 /* digits per line */ +#define SLEEP 1 /* seconds to sleep between digits */ + +int +main(int argc, char **argv) +{ + int i, j; + + setvbuf(stdout, NULL, _IONBF, 0); + for (i=0; i