Commit 3cf69bc0 authored by Seblu's avatar Seblu

defining archi.

parents
SUBDIRS = src
noinst_DATA=42sh$(EXEEXT)
DISTCLEANFILES=42sh$(EXEEXT)
.PHONY: tar doc re
42sh$(EXEEXT): src/42sh$(EXEEXT)
cp -f src/42sh$(EXEEXT) .
tar: distcheck
re: clean all
doc:
cd $(srcdir)/doc && $(MAKE) doc
CLEANFILES= *~ '\#*'
EXTRA_DIST = AUTHORS README TODO
#!/bin/sh
## bootstrap for 42sh in /home/seblu/devel/c/42sh
##
## Made by Seblu
## Login <seblu@epita.fr>
##
## Started on Sun Jul 16 19:43:53 2006 Seblu
## Last update Sun Jul 16 19:44:01 2006 Seblu
##
# Failures do matter.
set -e
# See what i'am doing
set -x
# install the GNU Build System.
autoreconf -i -f -v
# FIXME: autoheader does not obey --force.
find . -name 'config.h.in' | xargs touch
\ No newline at end of file
# Require a recent version of autotools
AC_PREREQ(2.59)
# Auto conf init
AC_INIT([42sh],[1.0],[seblu@seblu.net], [42sh])
# Define configure generator directory
AC_CONFIG_AUX_DIR([build])
# Auto Make init
AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip])
echo "Checking locale CFLAGS"
# Check platform
AC_CANONICAL_HOST
case $host_os in
*netbsd*)
AC_SUBST([CFLAGS], ['-Wall -Werror -W -ansi -pedantic'])
;;
*osf*)
AC_SUBST([CFLAGS], ['-Wall -Werror -W -ansi -pedantic -D_XOPEN_SOURCE=600'])
;;
*solaris*)
AC_SUBST([CFLAGS], ['-Wall -Werror -W -ansi -pedantic -D_XOPEN_SOURCE=600'])
;;
*linux*)
AC_SUBST([CFLAGS], ['-Wall -Werror -W -ansi -pedantic -D_XOPEN_SOURCE=600'])
;;
*)
pl="`uname -s`"
AC_MSG_ERROR([Platform $pl not supported.])
;;
esac
# Check for C compiler
AC_LANG([C])
AC_PROG_CC
# Check for Make
AC_PROG_MAKE_SET
# check for ranlib
AC_PROG_RANLIB
# Check for lib efence
AC_CHECK_LIB([efence], [malloc], [EFENCELIB=-lefence])
AC_SUBST([EFENCELIB])
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_CLOSEDIR_VOID
AC_FUNC_REALLOC
AC_FUNC_FORK
AC_FUNC_STAT
AC_FUNC_ALLOCA
AC_HEADER_DIRENT
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([malloc.h])
AC_CHECK_FUNCS([strtol])
AC_CHECK_FUNCS([dup])
AC_CHECK_FUNCS([dup2])
AC_CHECK_FUNCS([strchr])
AC_CHECK_FUNCS([strdup])
AC_CHECK_FUNCS([getcwd])
AC_CHECK_FUNCS([setenv])
AC_CHECK_FUNCS([strdup])
AC_CHECK_FUNCS([strstr])
AC_CHECK_FUNCS([get_current_dir_name])
AC_CHECK_FUNCS([atexit])
AC_CHECK_FUNCS([putenv])
AC_CHECK_FUNCS([strtoul])
AC_TYPE_PID_T
AC_TYPE_SIZE_T
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
# Check for headers
AC_CHECK_HEADERS([sys/param.h unistd.h])
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([libintl.h])
AC_CHECK_HEADERS([stddef.h])
dnl Memo:
dnl AC ARG WITH(package, help-string, [action-if-given], [action-if-not-given])
AC_ARG_WITH([debug],
[AS_HELP_STRING([--with-debug], [use -g and don't use -DNDEBUG -O3])],
[dnl action-if-given: --with-debug => -g || --without-debug => -DNDEBUG
if test x$withval = xyes; then
CFLAGS="$CFLAGS -g"
else
CFLAGS="$CFLAGS -DNDEBUG -O3"
fi
],
[dnl action-if-not-given: MAINTAINER_MODE => -g || !MAINTAINER_MODE => -DNDEBUG
# If we are in maintainer mode, we want to have DEBUG (NDEBUG==NO DEBUG)
# So we simply replace -DNDEBUG by -g
if test x$MAINTAINER_MODE = xyes; then
CFLAGS="$CFLAGS -g"
else
CFLAGS="$CFLAGS -DNDEBUG -O3"
fi
]
)
AC_ARG_WITH([leaktrack],
[AS_HELP_STRING([--with-leaktrack], [add a builtin leak track for debug])],
[
if test x$withval = xyes; then
CFLAGS="$CFLAGS -DLEAK_TRACK"
fi
],
)
AC_SUBST([CFLAGS])
# define Autoconf config header
AC_CONFIG_HEADERS([config.h])
# define Autoconf config files
AC_CONFIG_FILES([
Makefile
doc/Makefile
check/Makefile
check/leaktrack/Makefile
src/Makefile
src/parser/Makefile
src/evalexpr/Makefile
])
AC_CONFIG_FILES([check/checker_wrapper.sh],
[chmod a=rx check/checker_wrapper.sh])
AC_OUTPUT
SUBDIRS=ast builtin lexer parser
bin_PROGRAMS=42sh
#42sh_LDADD = parser/libparse.a ../check/leaktrack/libmem.a evalexpr/libevalexpr.a
42sh_SOURCES= shell/shell.h \
shell/shell_entry.c \
shell/shell_init.c \
shell/shell_destroy.c
# EXTRA_DIST= \
# parser/parse42.y \
# parser/scan42.l \
# evalexpr/evalexpr.y \
# evalexpr/evalexpr.l
CLEANFILES= *~ '\#*'
/*
** exec_and.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 15:27:20 2006 Seblu
** Last update Sun Apr 9 12:04:03 2006 SIGOURE Benoit
*/
#include "execution.h"
#include "mem.h"
/*!
** Execution an AND node
**
** @param node node to treat
** @param sh sh data
*/
void exec_and(struct s_op *node, struct s_42sh *sh)
{
assert(node && sh);
exec_node(node->left, sh);
if (!sh->last_status)
exec_node(node->right, sh);
}
/*
** exec_bang.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 15:27:20 2006 Seblu
** Last update Sun Apr 9 12:04:03 2006 SIGOURE Benoit
*/
#include "execution.h"
#include "mem.h"
/*!
** Execution a BANG node
**
** @param node node to treat
** @param sh sh data
*/
void exec_bang(struct s_op *node, struct s_42sh *sh)
{
assert(node && sh && !node->left);
exec_node(node->left, sh);
sh->last_status = !sh->last_status;
}
/*
** exec_cmd.c for 42sh in /home/seblu/devel/c/42sh/src/execution
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Apr 8 07:38:48 2006 Seblu
** Last update Sun May 21 17:07:27 2006 Seblu
*/
#define DEBUG_EXEC 0
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "../main/42sh.h"
#include "../ast/ast.h"
#include "execution.h"
#include "../builtin/builtin.h"
#include "../var/var.h"
#include "../globbing/quoting.h"
#include "../history/history.h"
#include "../expand/expand.h"
#include "mem.h"
#define rederror(prompt) do { perror(prompt); return 0; } while (0)
struct s_reds_context
{
int old;
int save;
int end;
};
static void create_fork(struct s_cmd *cmd, struct s_42sh *sh);
static void launch_cmd(struct s_cmd *cmd);
static int apply_reds(struct s_redir **reds);
static void parse_prefix(char **prefix, int glob, struct s_42sh *s);
static struct s_reds_context *save_reds_context(struct s_redir **reds);
static void restore_reds_context(struct s_reds_context *context);
static int get_filedes(const char *txt);
static void cmd_debugger(struct s_cmd *cmd);
/*!
** Execute a command node
**
** @param cmd cmd to execute
** @param sh sh params
*/
void exec_cmd(struct s_cmd *cmd, struct s_42sh *sh)
{
struct s_reds_context *context;
assert(cmd && sh);
if (DEBUG_EXEC)
cmd_debugger(cmd);
word_expansion(&cmd->argv, sh);
if (!cmd->argv)
{
parse_prefix(cmd->assign_words, 0, sh);
return;
}
if (is_a_builtin(cmd->argv[0], sh))
{
context = save_reds_context(cmd->redirs);
if (!apply_reds(cmd->redirs))
sh->last_status = RED_ERROR;
else
sh->last_status = exec_builtin(cmd, sh);
restore_reds_context(context);
free(context);
}
else
create_fork(cmd, sh);
}
/*!
** Execute a command in a pipeline. This call preserve for too many system call fork
** Take care, this must be called after a fork
**
** @param cmd cmd to execute
** @param sh sh structure
*/
void exec_piped_cmd(struct s_cmd *cmd, struct s_42sh *sh)
{
assert(cmd && sh);
if (DEBUG_EXEC)
cmd_debugger(cmd);
word_expansion(&cmd->argv, sh);
if (!apply_reds(cmd->redirs))
exit(RED_ERROR);
if (is_a_builtin(cmd->argv[0], sh))
sh->last_status = exec_builtin(cmd, sh);
else
{
parse_prefix(cmd->assign_words, 1, sh);
launch_cmd(cmd);
}
}
/*!
** Set redirection for builtin
**
** @param reds redirection informations
**
** @return save of all fd permutations
*/
static struct s_reds_context *save_reds_context(struct s_redir **reds)
{
struct s_reds_context *context;
register int i;
for (i = 0; reds[i]; ++i)
;
secmalloc(context, (i + 1) * sizeof (struct s_reds_context));
for (i = 0; reds[i]; ++i)
{
context[i].old = reds[i]->fd;
context[i].save = dup(reds[i]->fd);
context[i].end = 0;
}
context[i].end = 1;
return context;
}
static void restore_reds_context(struct s_reds_context *context)
{
register int i;
for (i = 0; !context[i].end; ++i)
dup2(context[i].save, context[i].old);
}
/*!
** Manage fork enterpise for a command
**
** @param cmd command to execute
** @param sh shell struct
*/
static void create_fork(struct s_cmd *cmd, struct s_42sh *sh)
{
pid_t pid;
int status;
if ((pid = fork()) == -1)
{
fprintf(stderr, "42sh: Cannot fork\n");
sh->last_status = FORK_ERROR;
return;
}
if (pid)
{
waitpid(pid, &status, 0);
sh->last_status = WEXITSTATUS(status);
}
else
{
parse_prefix(cmd->assign_words, 1, sh);
if (!apply_reds(cmd->redirs))
exit(RED_ERROR);
launch_cmd(cmd);
}
}
/*!
** Certify a correct changement of context
**
** @param cmd Execute a command
*/
static void launch_cmd(struct s_cmd *cmd)
{
execvp(cmd->argv[0], cmd->argv);
if (errno == ENOENT)
if (strchr(cmd->argv[0], '/') == NULL)
fprintf(stderr, "42sh: %s: command not found\n", cmd->argv[0]);
else
fprintf(stderr, "42sh: %s: No such file or directory\n", cmd->argv[0]);
else
perror("42sh");
exit((errno == ENOENT) ? 127 : 126);
}
/*!
** Parse prefix of command, and set variable local or global.
**
** @param prefix assignment words list
** @param glob variable set is global only or local
** @param sh shell info
*/
static void parse_prefix(char **prefix, int glob, struct s_42sh *sh)
{
register int i;
char *value;
if (!prefix)
return;
for (i = 0; prefix[i]; ++i)
{
if (!(value = strchr(prefix[i], '=')))
assert(0);
*value++ = 0;
if (glob)
var_setenv(prefix[i], value, !0);
else
var_set(sh->vars, prefix[i], value, !0);
}
}
/*!
** Apply redirections whitout save of file descriptors
**
** @param reds list of redirections
*/
static int apply_reds(struct s_redir **reds)
{
int fd;
int i;
char *filename;
assert(reds);
for (i = 0; reds[i]; ++i)
{
switch (reds[i]->type)
{
case R_LESS:
if ((fd = open(reds[i]->file, O_RDONLY)) == -1)
rederror("42sh");
dup2(fd, reds[i]->fd);
break;
case R_DLESSDASH:
case R_DLESS:
if ((fd = mkstemp(filename = strdup("42sh.heredocs.XXXXXX"))) == -1)
rederror("42sh");
write(fd, reds[i]->file, strlen(reds[i]->file));
lseek(fd, 0, SEEK_SET);
unlink(filename);
free(filename);
dup2(fd, STDIN_FILENO);
close(fd);
break;
case R_GREAT:
case R_CLOBBER:
if ((fd = open(reds[i]->file, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)
rederror("42sh");
dup2(fd, reds[i]->fd);
break;
case R_DGREAT:
if ((fd = open(reds[i]->file, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1)
rederror("42sh");
dup2(fd, reds[i]->fd);
break;
case R_GREATAND:
case R_LESSAND:
if ((fd = get_filedes(reds[i]->file)) == -1)
return 0;
if (fd == -2)
close(reds[i]->fd);
else
dup2(fd, reds[i]->fd);
break;
default:
return 0;
}
}
return 1;
}
/*!
** Retrieve an fd from and redirect words
**
** @param txt fd in string
**
** @return -1 if fail, -2 for close fd else fd
*/
static int get_filedes(const char *txt)
{
long fd;
char *endbuf;
assert(txt);
if (txt[0] == '-' && txt[1] == 0)
return -2;
fd = strtol(txt, &endbuf, 10);
if (endbuf == txt || *endbuf != 0)
{
fprintf(stderr, "42sh: %s: ambiguous redirect\n", txt);
return -1;
}
if (-1 == fcntl(fd, F_GETFL))
{
endbuf = strmerges(2, "42sh: ", txt);
perror(endbuf);
free(endbuf);
return -1;
}
return 0;
}
/*!
** Debug execution
**
** @param cmd command
*/
static void cmd_debugger(struct s_cmd *cmd)
{
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->assign_words && cmd->assign_words[i]; ++i)
fprintf(stderr, "prefix[%d] : %-15s\n", i, cmd->assign_words[i]);
for (i = 0; cmd->redirs && cmd->redirs[i]; ++i)
{
fprintf(stderr, "reds[%d] : type : %d\n", i, cmd->redirs[i]->type);
fprintf(stderr, " : fd : %d\n", cmd->redirs[i]->fd);
fprintf(stderr, " : file : %s\n", cmd->redirs[i]->file);
}
fprintf(stderr, "-----------------------------------\n");
}
/*
** exec_for.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 15:27:20 2006 Seblu
** Last update Sun May 21 18:46:45 2006 Seblu
*/
#include "execution.h"
#include "mem.h"
/*!
** Executre for instruction
**
** @param node node to treat
** @param sh sh info
*/
void exec_for(struct s_for *node, struct s_42sh *sh)
{
assert(node && sh);
assert(0);
node = node;
sh = sh;
/* explain for node */
}
/*
** exec_if.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 15:27:20 2006 Seblu
** Last update Sun Apr 9 12:04:03 2006 SIGOURE Benoit
*/
#include "execution.h"
#include "mem.h"
/*!
** Execute if struct.
**
** @param node if struct
** @param sh sh data
*/
void exec_if(struct s_if *node, struct s_42sh *sh)
{
assert(node && sh);
exec_node(node->cond, sh);
if (!sh->last_status)
exec_node(node->if_then, sh);
else
exec_node(node->if_else, sh);
}
/*
** exec_line.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 15:27:20 2006 Seblu
** Last update Sun Apr 9 12:04:03 2006 SIGOURE Benoit
*/
#include "execution.h"
#include "mem.h"
/*!
** Execution a line node
**
** @param node node to treat
** @param sh sh data
*/
void exec_line(struct s_op *node, struct s_42sh *sh)
{
assert(node && sh);
exec_node(node->left, sh);
if (node->right)
exec_node(node->right, sh);
}
/*
** exec_node.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 14:51:09 2006 Seblu
** Last update Sat Apr 15 09:12:38 2006 Seblu
*/
#include "execution.h"
#include "mem.h"
/*!
** Execute a node of ast by calling the good function
**
** @param node node to execute
** @param sh shell struct
*/
void exec_node(struct s_ast *node, struct s_42sh *sh)
{
assert(sh);
if (node == NULL)
return;
else if (node->type == T_CMD)
exec_cmd(&node->data.node_cmd, sh);
else if (node->type == T_PIPE)
exec_pipe(&node->data.node_op, sh);
else if (node->type == T_LINE)
exec_line(&node->data.node_op, sh);
else if (node->type == T_SEP_AND)
exec_sepand(&node->data.node_op, sh);
else if (node->type == T_SEP_SEMICOMMA)
exec_sepsemicolon(&node->data.node_op, sh);
else if (node->type == T_IF)
exec_if(&node->data.node_if, sh);
else if (node->type == T_FOR)
exec_for(&node->data.node_for, sh);
else if (node->type == T_AND)
exec_and(&node->data.node_op, sh);
else if (node->type == T_OR)
exec_or(&node->data.node_op, sh);
else if (node->type == T_WHILE)
exec_while(&node->data.node_while, sh);
else if (node->type == T_UNTIL)
exec_until(&node->data.node_while, sh);
else if (node->type == T_BANG)
exec_bang(&node->data.node_op, sh);
else if (node->type == T_SUBSHELL)
exec_subshell(&node->data.node_subshell, sh);
else
assert(0);
}
/*
** exec_and.c for 42sh in /home/seblu
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sat Mar 25 15:27:20 2006 Seblu
** Last update Sun Apr 9 12:04:03 2006 SIGOURE Benoit
*/
#include "execution.h"
#include "mem.h"
/*!
** Execution an OR node
**
** @param node node to treat
** @param sh sh data
*/
void exec_or(struct s_op *node, struct s_42sh *sh)
{
assert(node && sh);
exec_node(node->left, sh);
if (sh->last_status)
exec_node(node->right, sh);
}