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

typedef struct dent {
  char *name;
  struct stat st;
  int ents;
  struct dent *dir;
} d_ent;

int filter(const struct dirent *de)
{
  if (strcmp(de->d_name, ".") == 0) return 0;
  if (strcmp(de->d_name, "..") == 0) return 0;
  if (strcmp(de->d_name, "db.db") == 0) return 0;
  return 1;
}

d_ent *tree(char *path, int *ents)
{
  d_ent *de;
  char npath[PATH_MAX];
  struct dirent **dents;
  int i, n;

  n = scandir(path, &dents, filter, alphasort);
  de = malloc(sizeof(d_ent) * n);
  for(i=0; i < n; i++) {
    de[i].name = strdup(dents[i]->d_name);
    sprintf(npath, "%s/%s", path, dents[i]->d_name);
    lstat(npath, &(de[i].st));
    if (S_ISDIR(de[i].st.st_mode)) {
      de[i].dir = tree(npath, &(de[i].ents));
    } else {
      de[i].dir = NULL;
      de[i].ents = 0;
    }
  }
  *ents = n;
  return de;
}

void printtree(d_ent *de, int n, char *indent)
{
  char ind[PATH_MAX], *end;
  int i;

  strcpy(ind, indent);
  end = ind+strlen(ind);

  for(i=0; i < n; i++) {
    printf("%s%s%s\n", indent, ((i==(n-1))? "`-- ":"|-- "), de[i].name);
    if (de[i].dir != NULL) {
      strcpy(end, ((i==(n-1))? "    ": "|   "));
      printtree(de[i].dir, de[i].ents, ind);
    }
  }
}

int main(int argc, char *argv[])
{
  d_ent *de;
  int n;

  if (argc < 2) {
    fprintf(stderr,"%s <path>\n", argv[0]);
    exit(1);
  }
  
  de = tree(argv[1], &n);
  printf("%s\n", argv[1]);
  printtree(de, n, "");
}
