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

char** history;
int    history_pos;
int    history_size;
int    quit;

void history_add(const char* commandline)
{
  history[history_pos++] = strdup(commandline);

  if (history_pos >= history_size)
    history_pos = 0;
}

void history_print()
{
  int i;

  for(i = history_pos; i < history_size; ++i) {
    if (history[i])
      puts(history[i]);
  }

  for(i = 0; i < history_pos; ++i) {
    if (history[i])
      puts(history[i]);
  }
}

void shell_init(int argc, char** argv)
{
  quit = 0;

  if (argc == 2) {
    if (sscanf(argv[1], "%d", &history_size) != 1) {
      printf("Couldn't parse HISTORYSIZE '%s', must be a number", argv[1]);
      exit(EXIT_FAILURE);
    } else {
      int i;
      history_pos = 0;
      history = malloc(history_size * sizeof(char*));
      for(i = 0; i < history_size; ++i) {
        history[i] = 0;
      }
    }
  } else {
    printf("Usage: %s HISTORYSIZE\n", argv[0]);
    exit(EXIT_FAILURE);
  }
}

void shell_deinit()
{
  int i;
  for(i = 0; i < history_size; ++i) {
    if (history[i]) {
      free(history[i]);
    }
  }
  free(history);
}

void eval(char* buf)
{
  if (strcmp(buf, "history") == 0)
    {
      history_print();
    }
  else if (strcmp(buf, "logout") == 0)
    {
      quit = 1;
    }
  else
    {
      pid_t pid = fork();
      if (pid == 0)
        {
          char* args[2];
          args[0] = buf;
          args[1] = NULL;
          if (execvp(buf, args) == -1)
            {
              perror(buf);
            }
        }
      else
        {
          int status;
          wait(&status);
          if (status != 0)
            printf("Error: %d\n", status);
        }
    }
}

char* read_line()
{
  char buf[1024];
  
  fgets(buf, 1024, stdin);

  int i = 0;
  while(buf[i])
    {
      if (buf[i] == '\n')
        buf[i] = '\0';
      ++i;
    }

  return strdup(buf);
}

char** tokenize(char* buf)
{
  return 0;
}

void read_eval()
{
  while(!quit) {
    printf("shell> ");
    fflush(stdout);

    char* buf = read_line();
    history_add(buf);
    eval(buf);
    free(buf);
  }
}

int main(int argc, char** argv)
{
  shell_init(argc, argv);
  read_eval();
  shell_deinit();
  return 0;
}


