#ifdef ournix #include "ournix.h" #endif char sccsID[] = "@(#) block.c V1.0 Copyright Julian H. Stacey, Munich, 1990 04 06.\n"; /* FUNCTION : filter to output in fixed size blocks BUG: on Symmetric pipe I/O can be written to in 64K chunks, but is passed to read process in 4096 byte chunks summary: this prog works fine, but system IO doesnt!. */ #include char **ARGV; typedef char FLAG ; typedef int fd ; main(argc,argv) int argc ; char **argv ; { extern int atoi() ; extern char *malloc() ; int block_size ; long wr_cumulative = 0L ; long rd_cumulative = 0L ; fd fd_rd, fd_wr ; FLAG flush_f ; unsigned char *base_p, *tmp_p ; unsigned contents ; int got ; int want ; FLAG verbose_f = 0 ; ARGV = argv ; #ifdef VSL /* { */ #include "../../include/vsl.h" #endif /* } */ if (argc != 2) syntax() ; block_size = atoi(*++argv) ; if (block_size <= 0) syntax() ; if (block_size > 4096) { fprintf(stderr, "%s: Warning pipe(2) only passes up to 4096 bytes at a time to next process.\n", *ARGV); /* you can see this happening by compiling with verbose_f = 1, and a command like cp a.out b.out cat /dev/tape | a.out | b.out > /dev/null all unixes suffer the same problem, one way out with BSD4.2 is to rewrite this program with socketpair(2) */ } /* make a buffer */ if ((base_p = (unsigned char *)malloc((unsigned)block_size)) == (unsigned char *)0) { fprintf(stderr,"%s: Error: malloc(%d) failed.\n",*ARGV,block_size) ; perror(*ARGV) ; exit(1) ; } fd_rd = fileno(stdin) ; fd_wr = fileno(stdout) ; for(;;) { /* write blocks forever */ tmp_p = base_p ; contents = 0 ; flush_f = 0 ; while((contents < block_size) && (flush_f == 0) ) { /* read enough for a block */ want = block_size - contents ; if (verbose_f) fprintf(stderr, "%s Started reading %d bytes.\n", *ARGV, (int)want) ; fflush(stderr); got = read(fd_rd, (char *)tmp_p, (int)want ) ; if (verbose_f) fprintf(stderr, "%s Finished reading %d bytes.\n", *ARGV, got) ; fflush(stderr); if (got > 0) { tmp_p += got ; contents += got ; rd_cumulative += got ; } if (got == 0) flush_f = 1 ; if (got < 0) { fprintf(stderr, "%s: Error: read error after %ld previous bytes.\n", rd_cumulative ) ; exit(1) ; } } if (verbose_f) fprintf(stderr, "%s Started writing %d bytes.\n", *ARGV, (int)contents) ; fflush(stderr); if ( (got = write(fd_wr, (char *)base_p, (int)contents ) ) != contents ) { fprintf(stderr, "%s: Error: Wrote %d bytes after %ld bytes previously written.\n", *ARGV, got, wr_cumulative) ; exit(1) ; } if (verbose_f) fprintf(stderr, "%s Finished writing %d bytes.\n", *ARGV, got) ; fflush(stderr); wr_cumulative += contents ; if (flush_f == 1) break ; } exit(0); } syntax() { fprintf(stderr, "Syntax Error:\nWriting_process | %s block_size | Reading_process\n", *ARGV); exit(1) ; }