#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void putstr(char *str)
{
  write(STDOUT_FILENO, str, strlen(str));
}

void putcha(char ch)
{
  write(STDOUT_FILENO, &ch, 1);
}

void printbyte(unsigned char num)
{
  char *digits = "0123456789ABCDEF";

  putcha(digits[(num>>4) & 0xF]);
  putcha(digits[num & 0xF]);
}

void printoffset(unsigned int off)
{
  printbyte(off>>24 & 0xFF);
  printbyte(off>>16 & 0xFF);
  printbyte(off>>8  & 0xFF);
  printbyte(off     & 0xFF);
}

int main(int argc, char *argv[])
{
  int fd = STDIN_FILENO;
  
  if (argc > 1) {
    fd = open(argv[1], O_RDONLY);
    if (fd < 0) {
      putstr("Unable to open file for reading\n");
      return 1;
    }
  }
  
  int offset = 0, r, i;
  unsigned char buf[16];
  
  while ((r = read(fd, buf, 16)) > 0) {
    printoffset(offset);
    putcha(':');
    for(i = 0; i < r; i++) {
      putcha(' ');
      if (i == 8) putcha(' ');
      printbyte(buf[i]);      
    }
    for(; i < 16; i++) {
      putcha(' ');
      if (i == 8) putcha(' ');
      putcha(' ');
      putcha(' ');
    }
    putcha(' ');
    putcha(':');
    putcha(' ');
    for(i = 0; i < r; i++) {
      if (buf[i] < 32 || buf[i] > 126) putcha('.');
      else putcha(buf[i]);
    }
    putcha('\n');
  }

  return 0;
}