#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	<stdio.h>
#include <stdlib.h>
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) ;
	}
