Skip to content
Snippets Groups Projects
command.c 3.67 KiB
Newer Older
Sébastien Gendre's avatar
Sébastien Gendre committed
// Command representation and manipulation
// Sébastien Gendre <seb@k-7.ch>

#include "command.h"

cmd_t *command_from_str(char *str) {
Sébastien Gendre's avatar
Sébastien Gendre committed

  char *str_copy = malloc((strlen(str)+1)*sizeof(char));
  // Generate the command
  cmd_t *cmd = malloc(sizeof(cmd_t));
  // Store next command argument, used in the do…while loop
  char* next_arg;

  // Work with a copy of the given str
  strcpy(str_copy, str);
  
  // If malloc didn't work
  if (cmd == NULL) {
    perror("Malloc error for new command");
    return (cmd_t *)NULL;
  }
  // Initialize a simple command (empty, simple, foreground)
  cmd->type = JOB;
Sébastien Gendre's avatar
Sébastien Gendre committed
  cmd->argv = NULL;
Sébastien Gendre's avatar
Sébastien Gendre committed
  cmd->foreground = true;
  
  // Extract the command arguments
  do {

    if (cmd->argc == 0) {
      // Extract the commmand name
      next_arg = strtok(str_copy, ARGS_DELIMITERS);
      next_arg = strtok(NULL, ARGS_DELIMITERS);
    // Extend the cmd->argv array with a new char pointer
    cmd->argv = realloc(cmd->argv, (cmd->argc+1)*sizeof(char*));
    if( cmd->argv == NULL) {
      // In case the reallocation didn't work
      die_errno("parse_command::realloc");
    }
    
    // Store the argument inside cmd->argv
    cmd->argv[cmd->argc] = next_arg;

    if (next_arg != NULL) {
      // A new non null element will be added to cmd->argv
      cmd->argc += 1;
Sébastien Gendre's avatar
Sébastien Gendre committed
    }
  } while (next_arg != NULL);
Sébastien Gendre's avatar
Sébastien Gendre committed

  // Define the command type
  if (builtin_is_command_builtin(cmd->argc, cmd->argv)) {
    cmd->type = BUILTIN;
  } else {
    cmd->type = JOB;
  }

  return cmd;
}


/* Parse a string to get a pipeline of commands */
cmd_t *command_pipeline_from_str(char *str){
  char **commands = NULL;
  char *next_command = NULL;
  int commands_count = 0;
  cmd_t *previous_command = NULL;
  cmd_t *first_command = NULL;

  // Cut str into a list of commands string
  do {
    if (commands_count == 0) {
      // Extract the first command
      next_command = strtok(str, COMMAND_PIPE_DELIMITER);
    } else {
      // Get the next command
      next_command = strtok(NULL, COMMAND_PIPE_DELIMITER);
    }

    // Extend the command list to add a new command
    commands = realloc(commands, (commands_count+1)*sizeof(char *));
    if( commands == NULL) {
      // In case the reallocation didn't work
      die_errno("parse_command::realloc");
    }

    // Store the next command
    commands[commands_count] = next_command;

    if (next_command != NULL) {
      // A now command has been added
      commands_count += 1;
    }
    } while (next_command != NULL);

  // For each command string, create a command struct
  for (int i = 0; i < commands_count; ++i) {
    if (previous_command == NULL) {
      first_command = command_from_str(commands[i]);
    } else {
      previous_command->next = command_from_str(commands[i]);
    }
  }

  return first_command;
Sébastien Gendre's avatar
Sébastien Gendre committed
}

void command_dispose(cmd_t *cmd) {
  // Free all the command arguments str inside argv
  /* for (int i = 0; i < cmd->argc; ++i) { */
  /*   free(cmd->argv[i]); */
  /* } */
  // Free argv
Sébastien Gendre's avatar
Sébastien Gendre committed
  free(cmd->argv);
  // Then, finally, free the command
  free(cmd);
}


/* Fee a pipeline of command from the given command  */
void command_free_pipeline(cmd_t *cmd) {
  if (cmd->next != NULL) {
    command_free_pipeline(cmd->next);
  } else {
    command_dispose(cmd);
  }
Sébastien Gendre's avatar
Sébastien Gendre committed
}
// Execute the commande
int command_pipeline_exec(cmd_t *cmd) {
  switch (cmd->type) {
  case BUILTIN: {
    return builtin_exec_builtin_command(cmd->argc, cmd->argv);
    break;
  }
  case PIZZA:
    printf("I'm no Pizza delivery man, I'm a Ninja Turtle. I eat Pizza\n");
    return 0;
    break;
  case JOB:
  default:
    return job_exec_command(cmd->argc, cmd->argv);
    break;
  }