package main

// import "io" // IO has something just like what we want - except it uses a constant blocksize
import "os"
import "fmt"
import "flag"
import "syscall"

// const bufsize uint64 = 1024*1024
const bufsize uint64 = 32768
// const bufsize = 32

func usage(retval int)
	{
	fmt.Fprintf(os.Stderr, "Usage: snapcat [--max-length n]\n");
	os.Exit(retval);
	}

// I'm a little surprised the math package doesn't appear to have a min, but whatever
func min(left, right uint64) (uint64)
	{
	// Without the result variable, that is, with two returns, I get a compiler error about not returning
	// a value
	var result uint64;
	if (left <= right)
		{
		result = left
		}
	else
		{
		result = right
		}
	return result;
	}

func main()
	{
	var max_length *int64 = flag.Int64("max-length", -1, "Maximum number of bytes to transfer");
	var amount_written int64;
	var err os.Error;
	var this_block_length uint64;
	flag.Parse();
	for amount_written = 0; *max_length < 0 || amount_written < *max_length;
		{
		var buffer [bufsize]byte;
		if (*max_length < int64(0))
			{
			this_block_length = bufsize;
			}
		else
			{
			this_block_length = min(bufsize, uint64(*max_length) - uint64(amount_written));
			}
		// FIXME: Why is this returning an int rather than a uint?
		length_read, e := syscall.Read(0, buffer[0:this_block_length]);
		if e != 0
			{
			err = os.Errno(e);
			fmt.Fprintf(os.Stderr, "Error while reading from stdin: %s\n", err);
			os.Exit(1);
			}
		amount_written += int64(length_read);
		// fmt.Fprintf(os.Stderr, "Read %d so far\n", amount_written);
		if length_read == 0
			{
			// EOF
			break;
			}
		var length_written int;
		var amount_to_write uint64;
		// FIXME: Why is this returning an int rather than a uint?
		for amount_to_write = this_block_length; amount_to_write > 0; amount_to_write -= uint64(length_written)
			{
			length_written, e = syscall.Write(1, buffer[0:this_block_length]);
			if e != 0
				{
				err = os.Errno(e);
				fmt.Fprintf(os.Stderr, "Error while writing to stdout: %s\n", err);
				os.Exit(1);
				}
			}
		}
	}