#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <openssl/md5.h>
#include <openssl/sha.h>

#define BUFSIZE 1024

char str[] = "abcdefghijklmnopqrstuvwxyz"
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "0123456789+=-.";

char *
generate_passwd(int len)
{
  u_char *buffrand = (char*)malloc((len + 1) * sizeof(char));
  u_char *buffres = (char*)malloc((len + 1) * sizeof(char));
  int fd, i;
  int string_len = strlen(str);

  if(buffrand == NULL || buffres == NULL) {
    fprintf(stderr, "Memory error\n");
    exit(-1);
  }

  printf("Be aware that generating a password uses /dev/random.\n");
  fd = open ("/dev/random", O_RDONLY);
  if(fd == -1) {
    perror("open");
    exit(-1);
  }

  if(read(fd, buffrand, len) != len) {
    perror("read");
    exit(-1);
  }

  for(i = 0; i < len; i ++) {
    buffres[i] = str[buffrand[i] % string_len];
  } 

  buffres[i] = '\0';

  free(buffrand);
  close(fd);
  return(buffres);
}

int
md5file(char *fn, unsigned char *digest)
{
  unsigned char buf[BUFSIZE];
  MD5_CTX ctx;
  int n;
  int fd;

  fd = open(fn, O_RDONLY);
  if (fd == -1) {
    perror("open");
    exit(-1);
  }

  MD5_Init(&ctx);
  while ((n = read(fd, buf, sizeof(buf))) > 0)
    MD5_Update(&ctx, buf, n);
  MD5_Final(digest, &ctx);

  close(fd);

  return 0;
}

int
sha1file(char *fn, unsigned char *digest)
{
  unsigned char buf[BUFSIZE];
  SHA_CTX ctx;
  int n;
  int fd;

  fd = open(fn, O_RDONLY);
  if (fd == -1) {
    perror("open");
    exit(-1);
  }

  SHA1_Init(&ctx);
  while ((n = read(fd, buf, sizeof(buf))) > 0)
    SHA1_Update(&ctx, buf, n);
  SHA1_Final(digest, &ctx);

  close(fd);

  return 0;
}

void
print_digest(unsigned char *p, int len)
{
  int i;

  for (i = 0; i < len; ++i)
    printf("%02x", *p++);

  return ;
}

int
main(int argn, char **argv)
{
  int p;
  char buffres[32 + 1];

  if(argn != 2) {
    printf("Usage: %s <file>\n", argv[0]);
    exit(-1);
  }

  memset(buffres, 0, sizeof(buffres));

  p = md5file(argv[1], buffres);
  printf("MD5(");
  print_digest(buffres, MD5_DIGEST_LENGTH);
  printf(")  %s\n", argv[1]);

  p = sha1file(argv[1], buffres);
  printf("SHA1(");
  print_digest(buffres, SHA_DIGEST_LENGTH);
  printf(")  %s\n", argv[1]);

  printf("PASSWD(%s) %i\n", generate_passwd(8), 8);

  return 0;
}

