/*
 *	Produces a checksum of a byte stream that should be the same as
 *	the standard SVR4 "sum" program.  Note that the "sum" documentation
 *	is misleading, the checksum is NOT simply a 16-bit checksum of all
 *	the bytes.  Here is the algorithm:
 *
 *	1.	Add up all the bytes using an unsigned long (32-bit)
 *		integer and treating each byte as unsigned.
 *
 *	2.	Add the overflow from the lower 16 bits (the high 16
 *		bits) back into the lower 16 bits using unsigned
 *		arithmetic.  I.E. treat the 32-bit long as two 16-bit
 *		unsigned ints and add them using 32-bit unsigned
 *		arithmetic.
 *
 *	3.	Repeat step (2) one more time, presumably to catch
 *		any additional overflow.
 *
 *	If stdout is not a terminal, then the input is passed on to the
 *	output, and the checksum is printed on stderr rather than stdout.
 *	This allows natural use as either the end of a pipeline with the
 *	checksum printed on stdout, or in the middle with it printed on
 *	stderr.
 *
 *	Written by Fred Fish.  This file is public domain.
 */

#include <stdio.h>

#define BFSIZ 1024

main ()
{
  unsigned char buf[BFSIZ];
  int nbytes;
  unsigned long sum = 0;
  unsigned long temp = 0;
  int nopass;

  nopass = isatty (1);
  while ((nbytes = read (0, buf, sizeof (buf))) > 0)
    {
      if (!nopass)
	{
	  (void) write (1, buf, (unsigned) nbytes);
	}
      while (nbytes-- > 0)
	{
	  sum += buf[nbytes];
	}
    }
  temp = (sum >> 16) + (sum & 0xFFFF);
  sum = (temp >> 16) + (temp & 0xFFFF);
  if (nopass)
    {
      (void) fprintf (stdout, "%u\n", sum);
    }
  else
    {
      (void) fprintf (stderr, "%u\n", sum);
    }
  return (0);
}
