/*
** MD5 -- create MD5 message digests of files
**
** MD5 was created by RSA Inc.  See md5.c for more information.
**
** This wrapper program was created by:
**
** Seth Robertson
** seth@ctr.columbia.edu
**
** And is in the public domain (the wrapper only)
**
** Last modified 12/15/93 (leading zeros in output were stripped,
** missing last checksum byte).  Previous output (which was mostly
** correct) can be seen with -b (for those files already checksummed)
**
*/

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>

#ifdef RSAREF
#include "global.h"
#endif
#include "md5.h"

extern char *sys_errlist[];

char *format = "%02x";;

char *back = "%x";

main(int argc,char *argv[])

{
  int i,x;
  int fd;
  char *addr;
  struct stat buf;
  MD5_CTX mdContext;
#ifdef RSAREF
  u_char digest[16];
#endif /*RSAREF*/
  int stdinn=0;
  int digest_size = 16;
  int tmpvar;
  int getopterr = 0;
  extern char *optarg;
  extern int optind;


  while ((tmpvar = getopt(argc,argv, "b")) != -1)
    switch(tmpvar)
      {
      case 'b':
	format = back;
	digest_size = 15;
	break;
      case '?':
	getopterr++;
      }

  if (getopterr)
    {
      fprintf(stderr,"Usage: %s [-b] [<filename> ...]\n", argv[0]);
      exit(2);
    }

  if (optind >= argc)
    stdinn=1;

  for(;optind < argc || stdinn;optind++)
    {
      if (!stdinn)
	{
	  if ((fd = open(argv[optind],O_RDONLY)) < 0)
	    {
	      fprintf(stderr,"%s: Error: can not access %s (%s)\n",
		      argv[0],argv[optind],sys_errlist[errno]);
	      continue;
	    }
	  
	  if (fstat(fd, &buf) < 0)
	    {
	      fprintf(stderr,"%s: Error: can not stat %s (%s)\n",
		      argv[0],argv[optind],sys_errlist[errno]);
	      close(fd);
	      continue;
	    }
	  
	  if ((addr = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t)-1)
	    {
	      fprintf(stderr,"%s: Error: Can not mmap %s (%s)\n",
		      argv[0],argv[optind],sys_errlist[errno]);
	      close(fd);
	      continue;
	    }	  
	}

      MD5Init(&mdContext);

      if (stdinn)
	{
	  int bytes;
#if defined(__svr4__)
	  int bufsize = sysconf(_SC_PAGESIZE);
#else	  
	  int bufsize = getpagesize();
#endif

	  addr = malloc(bufsize);

	  while (bytes = read(0, addr, bufsize))
	    {
	      MD5Update(&mdContext, addr, bytes);
	    }

	  free(addr);
	}
      else
	MD5Update(&mdContext, addr, buf.st_size);

#ifdef RSAREF
      MD5Final(digest,&mdContext);
#else
      MD5Final(&mdContext);
#endif

      printf("%s:  ",stdinn?"stdin":argv[optind]);
      for(i=0;i<digest_size;i++)
#ifdef RSAREF
	printf(format,digest[i]);
#else
	printf(format,mdContext.digest[i]);
#endif
      printf("\n");

      if (!stdinn)
	{
	  munmap(addr, buf.st_size);
	  close(fd);
	}
      stdinn=0;
    }

}
