Skip to content
exec_cmd.c 3.35 KiB
Newer Older
Seblu's avatar
Seblu committed
/*
** exec_cmd.c for 42sh
Seblu's avatar
Seblu committed
**
** Made by Seblu
** Login   <seblu@epita.fr>
**
** Started on  Sat Apr  8 07:38:48 2006 Seblu
** Last update Thu Nov 23 11:28:39 2006 seblu
Seblu's avatar
Seblu committed
*/

#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
Seblu's avatar
Seblu committed
#include "exec.h"
Seblu's avatar
Seblu committed
#include "../builtin/builtin.h"
Seblu's avatar
Seblu committed
#include "../common/function.h"
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
/*
** ============
** DECLARATIONS
** ============
*/
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
static int		exec_program(s_cmd_node *cmd);
static void		exec_function(char **argv);
Seblu's avatar
Seblu committed
static void		exec_argv(char **argv);
static void		exec_prefix(char **prefix, int glob);
Seblu's avatar
Seblu committed

/*!
** Debug execution
**
** @param cmd command
*/
Seblu's avatar
Seblu committed
static void		cmd_debugger(s_cmd_node *cmd);
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
/*
** ===========
** DEFINITIONS
** ===========
*/

Seblu's avatar
Seblu committed
void			exec_cmd(s_cmd_node *cmd)
Seblu's avatar
Seblu committed
{
Seblu's avatar
Seblu committed
  assert(cmd);
Seblu's avatar
Seblu committed
  if (DEBUG_EXEC)
Seblu's avatar
Seblu committed
    cmd_debugger(cmd);
  //FIXME: expansions here
  if (!cmd->argv) {
    if (cmd->prefix) exec_prefix(cmd->prefix, 0);
    return;
Seblu's avatar
Seblu committed
  }
  if (func_exist(shell->func, cmd->argv[0]))
Seblu's avatar
Seblu committed
    exec_function(cmd->argv);
  else if (is_a_builtin(cmd->argv[0]))
    shell->status = get_builtin(cmd->argv[0])(cmd->argv);
Seblu's avatar
Seblu committed
  else
Seblu's avatar
Seblu committed
    shell->status = exec_program(cmd);
Seblu's avatar
Seblu committed
}

Seblu's avatar
Seblu committed
void			exec_piped_cmd(s_cmd_node *cmd)
{
  assert(cmd);
  if (DEBUG_EXEC)
    cmd_debugger(cmd);
  //FIXME: expansions here
  if (!cmd->argv) {
    if (cmd->prefix) exec_prefix(cmd->prefix, 0);
    return;
  }
  if (func_exist(shell->func, cmd->argv[0]))
Seblu's avatar
Seblu committed
    exec_function(cmd->argv);
  else if (is_a_builtin(cmd->argv[0]))
    shell->status = get_builtin(cmd->argv[0])(cmd->argv);
  else {
    if (cmd->prefix)
      exec_prefix(cmd->prefix, 1);
    exec_argv(cmd->argv);
  }
}

Seblu's avatar
Seblu committed
static int		exec_program(s_cmd_node *cmd)
Seblu's avatar
Seblu committed
{
Seblu's avatar
Seblu committed
  pid_t			pid;
  int			status;
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
  if ((pid = fork()) == -1) {
Seblu's avatar
Seblu committed
    fprintf(stderr, "%s: Cannot fork.\n", shell->name);
Seblu's avatar
Seblu committed
    return ERROR_FORK;
Seblu's avatar
Seblu committed
  }
Seblu's avatar
Seblu committed
  if (pid) {
    waitpid(pid, &status, 0);
    return WEXITSTATUS(status);
Seblu's avatar
Seblu committed
  }
Seblu's avatar
Seblu committed
  if (cmd->prefix)
    exec_prefix(cmd->prefix, 1);
  exec_argv(cmd->argv);
Seblu's avatar
Seblu committed
  //never reach
Seblu's avatar
Seblu committed
  assert(0);
Seblu's avatar
Seblu committed
  return 1;
Seblu's avatar
Seblu committed
}

Seblu's avatar
Seblu committed
static void		exec_argv(char **argv)
Seblu's avatar
Seblu committed
{
Seblu's avatar
Seblu committed
  assert(argv && argv[0]);
  execvp(argv[0], argv);
Seblu's avatar
Seblu committed
  if (errno == ENOENT)
Seblu's avatar
Seblu committed
    if (strchr(argv[0], '/') == NULL)
Seblu's avatar
Seblu committed
      fprintf(stderr, "%s: %s: command not found.\n", shell->name, argv[0]);
Seblu's avatar
Seblu committed
    else
Seblu's avatar
Seblu committed
      fprintf(stderr, "%s: %s: No such file or directory.\n",
Seblu's avatar
Seblu committed
	      shell->name, argv[0]);
Seblu's avatar
Seblu committed
  else
Seblu's avatar
Seblu committed
    perror(shell->name);
Seblu's avatar
Seblu committed
  exit((errno == ENOENT) ? 127 : 126);
}

Seblu's avatar
Seblu committed
static void		exec_prefix(char **prefix, int glob)
Seblu's avatar
Seblu committed
{
  char			*value;

Seblu's avatar
Seblu committed
  assert(prefix);
  for (int i = 0; prefix[i]; ++i) {
    if (!(value = strchr(prefix[i], '=')))
      assert(0);
    *value = 0;
    if (glob || getenv(prefix[i]) != NULL)
      setenv2(prefix[i], value + 1, !0);
Seblu's avatar
Seblu committed
    else
      var_add(shell->var, prefix[i], value + 1);
    *value = '=';
Seblu's avatar
Seblu committed
  }
}

Seblu's avatar
Seblu committed
static void		exec_function(char **argv)
{
  assert(argv && argv[0]);
  //FIXME: add arguments transmission here
  exec_node(func_get(shell->func, argv[0]));
}
Seblu's avatar
Seblu committed


Seblu's avatar
Seblu committed
static void		cmd_debugger(s_cmd_node *cmd)
Seblu's avatar
Seblu committed
{
Seblu's avatar
Seblu committed
  int			i;

  fprintf(stderr, "-----------------------------------\n");
  fprintf(stderr, "exec command\n");
  for (i = 0; cmd->argv && cmd->argv[i]; ++i)
    fprintf(stderr, "argv[%d]   : %-15s\n", i, cmd->argv[i]);
  for (i = 0; cmd->prefix && cmd->prefix[i]; ++i)
    fprintf(stderr, "prefix[%d] : %-15s\n", i, cmd->prefix[i]);
  fprintf(stderr, "-----------------------------------\n");
Seblu's avatar
Seblu committed
}