diff --git a/Makefile.am b/Makefile.am index 498b4af534551756a699347a06af6fab898a075b..22315e6417fcc5b10293dbd97e367ee1fe4892eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,12 @@ bin_PROGRAMS=42sh src/ast/ast_while.c \ src/builtin/builtin.h \ src/builtin/builtin.c \ + src/builtin/builtin_alias.c \ + src/builtin/builtin_cd.c \ + src/builtin/builtin_echo.c \ src/builtin/builtin_exit.c \ + src/builtin/builtin_unalias.c \ + src/builtin/builtin_shopt.c \ src/common/basename.c \ src/common/constant.h \ src/common/env.c \ @@ -34,6 +39,8 @@ bin_PROGRAMS=42sh src/exec/exec.h \ src/exec/exec_and.c \ src/exec/exec_bang.c \ + src/exec/exec_cmd.c \ + src/exec/exec_funcdec.c \ src/exec/exec_node.c \ src/exec/exec_or.c \ src/exec/exec_if.c \ @@ -41,13 +48,13 @@ bin_PROGRAMS=42sh src/exec/exec_sep.c \ src/exec/exec_sepand.c \ src/exec/exec_while.c \ - src/parser/alias.c \ - src/parser/alias.h \ src/parser/getline.c \ src/parser/getline.h \ src/parser/parser.c \ src/parser/parser.h \ src/parser/lexer.c \ + src/shell/alias.c \ + src/shell/alias.h \ src/shell/func.c \ src/shell/func.h \ src/shell/getoptions.c \ diff --git a/TODO b/TODO index 0f2839cc7bd5908071affa0ab01b2a09d5cac0a0..0519670c411e0d85a039b9447c173f0f6a41dab6 100644 --- a/TODO +++ b/TODO @@ -2,6 +2,7 @@ -- Voir probleme de syntax que j'accepte lorsque un EOF apparait avant une quote fermante. Le token est valide alors que sous bash non. faire un test avant. Maintenant il renvoie EOF a la place du token. +-- verifier toto \2>sex fonctionne. - Parser -- aliases diff --git a/configure.ac b/configure.ac index b15e549177a6c1beac00a87c813b3e0ff2c286d1..3f77a485a8d9608555bafd4f047312580ea94f49 100644 --- a/configure.ac +++ b/configure.ac @@ -112,7 +112,8 @@ AC_ARG_WITH([efence], [AS_HELP_STRING([--with-efence], [link with lib efence])], [dnl action-if-given LDFLAGS="$LDFLAGS -lefence" - CFLAGS="$CFLAGS -include stdlib.h -include efence.h" + test -r "/usr/include/efence.h" && + CFLAGS="$CFLAGS -include stdlib.h -include efence.h" ], [dnl action-if-not-given true diff --git a/src/ast/ast.h b/src/ast/ast.h index 9b32c6ed80241ee170fab9fe1609653160a7d07c..7fdba85d6775fca92c448ce0fc786543808573e6 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 30 04:40:03 2006 Seblu -** Last update Tue Oct 17 17:14:49 2006 seblu +** Last update Thu Nov 16 17:01:11 2006 seblu */ #ifndef AST_H_ @@ -179,6 +179,12 @@ struct ast_node u_node_item body; }; +/* +** ================= +** FILE: ast_print.c +** ================= +*/ + /*! ** Print an ast to @arg filename file ** @@ -197,6 +203,12 @@ void ast_print(s_ast_node *ast, const char *filename); */ void ast_print_node(s_ast_node *ast, FILE *fs, unsigned int *node_id); +/* +** ==================== +** FILE: ast_destruct.c +** ==================== +*/ + /*! ** Destroy node and all its childs ** @@ -213,6 +225,12 @@ void ast_destruct(s_ast_node *ast); */ void ast_destruct_node(s_ast_node *ast); +/* +** =========== +** ast_if.c +** =========== +*/ + /*! ** Create an if ast node ** @@ -248,6 +266,12 @@ void ast_if_destruct_node(s_ast_node *node); */ void ast_if_destruct(s_ast_node *node); +/* +** =============== +** FILE: ast_for.c +** =============== +*/ + /*! ** Create a for ast node ** @@ -285,6 +309,12 @@ void ast_for_destruct_node(s_ast_node *node); */ void ast_for_destruct(s_ast_node *node); +/* +** ================ +** FILE: ast_case.c +** ================ +*/ + /*! ** Create a case ast node ** @@ -329,6 +359,12 @@ void ast_case_destruct_node(s_ast_node *node); */ void ast_case_destruct(s_ast_node *node); +/* +** ================= +** FILE: ast_while.c +** ================= +*/ + /*! ** Create a while ast node ** @@ -362,6 +398,12 @@ void ast_while_destruct_node(s_ast_node *node); */ void ast_while_destruct(s_ast_node *node); +/* +** =============== +** FILE: ast_red.c +** =============== +*/ + /*! ** Create a redirection ast node ** @@ -405,6 +447,12 @@ void ast_red_destruct_node(s_ast_node *node); */ void ast_red_destruct(s_ast_node *node); +/* +** =============== +** FILE: ast_cmd.c +** =============== +*/ + /*! ** Create a cmd ast node ** @@ -451,6 +499,12 @@ void ast_cmd_destruct_node(s_ast_node *node); */ void ast_cmd_destruct(s_ast_node *node); +/* +** =============== +** FILE: ast_and.c +** =============== +*/ + /*! ** Create an and (&&) ast node ** @@ -484,6 +538,12 @@ void ast_and_destruct_node(s_ast_node *node); */ void ast_and_destruct(s_ast_node *node); +/* +** ============== +** FILE: ast_or.c +** ============== +*/ + /*! ** Create an or (||) ast node ** @@ -517,6 +577,12 @@ void ast_or_destruct_node(s_ast_node *node); */ void ast_or_destruct(s_ast_node *node); +/* +** ==================== +** FILE: ast_subshell.c +** ==================== +*/ + /*! ** Create a subshell (()) ast node ** @@ -549,6 +615,12 @@ void ast_subshell_destruct_node(s_ast_node *node); */ void ast_subshell_destruct(s_ast_node *node); +/* +** =================== +** FILE: ast_funcdec.c +** =================== +*/ + /*! ** Create a funcdec (function declaration) ast node ** @@ -582,6 +654,12 @@ void ast_funcdec_destruct_node(s_ast_node *node); */ void ast_funcdec_destruct(s_ast_node *node); +/* +** ================ +** FILE: ast_bang.c +** ================ +*/ + /*! ** Create a bang (!) ast node ** @@ -614,6 +692,12 @@ void ast_bang_destruct_node(s_ast_node *node); */ void ast_bang_destruct(s_ast_node *node); +/* +** ================ +** FILE: ast_pipe.c +** ================ +*/ + /*! ** Create a pipe (|) ast node ** @@ -646,6 +730,12 @@ void ast_pipe_destruct_node(s_ast_node *node); */ void ast_pipe_destruct(s_ast_node *node); +/* +** =============== +** FILE: ast_sep.c +** =============== +*/ + /*! ** Create a separtor (;) ast node ** @@ -678,6 +768,12 @@ void ast_sep_destruct_node(s_ast_node *node); */ void ast_sep_destruct(s_ast_node *node); +/* +** ================== +** FILE: ast_sepand.c +** ================== +*/ + /*! ** Create a sepand (&) ast node ** diff --git a/src/ast/ast_funcdec.c b/src/ast/ast_funcdec.c index 5421520399aa1720b03dca67ca3ee95e06e2312f..e0069658255ee9106554ae868d5e1981566e99a1 100644 --- a/src/ast/ast_funcdec.c +++ b/src/ast/ast_funcdec.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Wed Oct 18 17:14:16 2006 seblu +** Last update Thu Nov 16 17:07:14 2006 seblu */ #include "ast.h" @@ -38,7 +38,8 @@ void ast_funcdec_destruct_node(s_ast_node *node) { if (node->type != T_FUNCDEC) return; - free(node->body.child_funcdec.name); + if (node->body.child_funcdec.name) + free(node->body.child_funcdec.name); free(node); } @@ -46,7 +47,9 @@ void ast_funcdec_destruct(s_ast_node *node) { if (node->type != T_FUNCDEC) return; - free(node->body.child_funcdec.name); - ast_destruct(node->body.child_funcdec.body); + if (node->body.child_funcdec.name) + free(node->body.child_funcdec.name); + if (node->body.child_funcdec.body) + ast_destruct(node->body.child_funcdec.body); free(node); } diff --git a/src/builtin/builtin.c b/src/builtin/builtin.c index 5e63747e4af728e4b8e2ec272272719668954185..85f37082984e07752b0e6e6dd2f18f6cb94fa304 100644 --- a/src/builtin/builtin.c +++ b/src/builtin/builtin.c @@ -5,49 +5,50 @@ ** Login ** ** Started on Tue Apr 11 00:22:44 2006 Seblu -** Last update Sun Nov 12 19:56:53 2006 Seblu +** Last update Thu Nov 16 18:59:29 2006 seblu */ #include +#include #include "builtin.h" -enum { BUILTIN_COUNT = 7 }; +enum { BUILTIN_COUNT = 10 }; -typedef int (*f_builtin)(char *argv[]); - -struct builtin_table +struct builtin_table { - const char *name; - f_builtin func; + const char *name; + f_builtin func; }; static struct builtin_table builtin_table[BUILTIN_COUNT] = { - {"cd", NULL}, //builtin_cd}, - {"echo", NULL}, //builtin_echo}, + {"cd", builtin_cd}, + {"echo", builtin_echo}, {"exit", builtin_exit}, - {"shopt", NULL}, //builtin_shopt}, + {"shopt", builtin_shopt}, + {"alias", builtin_alias}, + {"unalias", builtin_unalias}, {"source", NULL}, //builtin_source}, + {"set", NULL}, //builtin_set}, {"unset", NULL}, //builtin_unset}, {"export", NULL}, //builtin_export} }; int is_a_builtin(const char *name) { - register int i; - - for (i = 0; i < BUILTIN_COUNT; ++i) + for (register int i = 0; i < BUILTIN_COUNT; ++i) if (!strcmp(name, builtin_table[i].name)) return 1; return 0; } -int exec_builtin(s_cmd_node *cmd) +f_builtin get_builtin(const char *name) { - register int i; - - for (i = 0; i < BUILTIN_COUNT; ++i) - if (!strcmp(cmd->argv[0], builtin_table[i].name)) - return builtin_table[i].func(cmd->argv); - return 0; + for (register int i = 0; i < BUILTIN_COUNT; ++i) + if (!strcmp(name, builtin_table[i].name)) { + assert(builtin_table[i].func); + return builtin_table[i].func; + } + assert(0); + return NULL; } diff --git a/src/builtin/builtin.h b/src/builtin/builtin.h index 4f50b3db500d0c2626fcca98d8a127437f718b48..aac80ad8264f710174fc27546f1f2dc0c9bcef88 100644 --- a/src/builtin/builtin.h +++ b/src/builtin/builtin.h @@ -5,26 +5,75 @@ ** Login ** ** Started on Sun Nov 12 16:46:24 2006 Seblu -** Last update Sun Nov 12 19:55:03 2006 Seblu +** Last update Thu Nov 16 17:49:13 2006 seblu */ #ifndef BUILTIN_H_ # define BUILTIN_H_ -# include -# include "../ast/ast.h" -# include "../shell/shell.h" +typedef int (*f_builtin)(char *argv[]); -int is_a_builtin(const char *name); -int exec_builtin(s_cmd_node *cmd); +/*! +** Says if @var name is a builtin. +** +** @param name builtin name +** +** @return boolean existance +*/ +int is_a_builtin(const char *name); + +/*! +** Return a pointer on a builtin function +** +** @param name builtin name +** +** @return pointer on the builtin function @var name +*/ +f_builtin get_builtin(const char *name); + +/*! +** Builtin Change Directory +** +** @param argv argument vector +** +** @return success status +*/ +int builtin_cd(char *argv[]); + +/*! +** Echo show all element on her line +** +** @param argc number of argument given +** +** @return sucess status +*/ +int builtin_echo(char *argv[]); + +/*! +** This builtin change local setting of the shell +** +** @param argv argument vector +** +** @return success status +*/ +int builtin_shopt(char *argv[]); + +/*! +** Builtin exit :) +** +** @param argv argument vector +** +** @return success status +*/ +int builtin_exit(char *argv[]); + +int builtin_source(char *argv[]); +int builtin_unset(char *argv[]); +int builtin_export(char *argv[]); + +int builtin_alias(char *argv[]); +int builtin_unalias(char *argv[]); -int builtin_cd(char *argv[]); -int builtin_echo(char *argv[]); -int builtin_shopt(char *argv[]); -int builtin_exit(char *argv[]); -int builtin_source(char *argv[]); -int builtin_unset(char *argv[]); -int builtin_export(char *argv[]); /* ** Bonus builtin diff --git a/src/builtin/builtin_alias.c b/src/builtin/builtin_alias.c new file mode 100644 index 0000000000000000000000000000000000000000..07aa11938ef85f8b56805ed1823b2615ca969fe3 --- /dev/null +++ b/src/builtin/builtin_alias.c @@ -0,0 +1,81 @@ +/* +** builtin_alias.c for 42sh +** +** Made by seblu +** Login +** +** Started on Thu Nov 16 17:18:24 2006 seblu +** Last update Thu Nov 16 19:27:01 2006 seblu +*/ + +#include +#include +#include +#include "builtin.h" +#include "../shell/shell.h" + +static int show_all_alias(void); +static int show_alias(const char *name); +static int getoption(char *argv[], int *argp, int *p); + +int builtin_alias(char *argv[]) +{ + int argp; + char *carg; + char *equal; + int show = 0; + + assert(argv && argv[0]); + if (!getoption(argv, &argp, &show)) + return 2; + if (argv[1] == NULL || show) + return show_all_alias(); + for (; (carg = argv[argp]); ++argp) { + if (!(equal = strchr(carg, '='))) + show_alias(carg); + else { + *equal = 0; + alias_add(shell->alias, strdup(carg), strdup(equal + 1)); + *equal = '='; + } + } + return 0; +} + +static int getoption(char *argv[], int *argp, int *p) +{ + char *carg; + + for (*argp = 1; (carg = argv[*argp]); ++*argp) + if (*carg == '-') + for (++carg; *carg; ++carg) + if (*carg == 'p') + *p = 1; + else { + fprintf(stderr, "%s: alias: -%c: invalid option.\n", + shell->name, *carg); + fprintf(stderr, "alias: usage: alias [-p] [name[=value]] ... ]\n"); + return 0; + } + return 1; +} + +static int show_alias(const char *name) +{ + for (size_t i = 0; i < shell->alias->count; ++i) + if (!strcmp(shell->alias->table[i].name, name)) { + printf("alias %s=%s\n", shell->alias->table[i].name, + shell->alias->table[i].value); + return 1; + } + printf("%s: alias: %s: not found.\n", shell->name, name); + return 0; +} + +static int show_all_alias(void) +{ + for (size_t i = 0; i < shell->alias->count; ++i) + printf("alias %s=%s\n", shell->alias->table[i].name, + shell->alias->table[i].value); + return 0; +} diff --git a/src/builtin/builtin_cd.c b/src/builtin/builtin_cd.c index f685ede5843b07903b6c38343cdef83717ff9d3e..0cd28f02c78946e2e7eefb068bed2bfe76082072 100644 --- a/src/builtin/builtin_cd.c +++ b/src/builtin/builtin_cd.c @@ -5,107 +5,82 @@ ** Login ** ** Started on Tue Apr 11 00:23:47 2006 Seblu -** Last update Sun Nov 12 19:55:57 2006 Seblu +** Last update Thu Nov 16 16:57:54 2006 seblu */ -#include #include #include #include -#include #include +#include #include -#include "../main/42sh.h" -#include "builtin.h" -#include "../var/var.h" +#include "../common/function.h" +#include "../shell/shell.h" +#include "../shell/var.h" -static int cd_var(struct s_42sh *sh, const char *name); -static int cd_minus(struct s_42sh *sh); -static int secure_chdir(const char *path); +/* +** ============ +** DECLARATIONS +** ============ +*/ /*! -** Builtin cd. -** @param argv The tab of args: terminated by NULL, argv[0] = "cd" -** @param sh The 42sh structure +** Change directory to home directory +** +** @param name env var +** +** @return success status */ -int builtin_cd(char **argv) +static int cd_var(const char *name); + +/*! +** Change of directory and on error, print good error. +** +** @param path new path +** +** @return error status with error code (0 is good) +*/ +static int secure_chdir(const char *path); + +/* +** =========== +** DEFINITIONS +** =========== +*/ + +int builtin_cd(char **argv) { - assert(sh && argv && argv[0]); + assert(argv && argv[0]); if (!argv[1]) - return cd_var(sh, "HOME"); + return cd_var("HOME"); if (!strcmp("-", argv[1])) - return cd_minus(sh); + return cd_var("OLDPWD"); return secure_chdir(argv[1]); } -/*! -** Change directory to home directory -** -** @param sh shell env -** @param name env var -** -** @return exit status -*/ -static int cd_var(struct s_42sh *sh, const char *name) +static int cd_var(const char *name) { const char *new_dir; - if (!(new_dir = var_get(sh->vars, name))) - { - fprintf(stderr, "42sh: cd: %s not set\n", name); + if (!(new_dir = var_get(shell->var, name))) { + fprintf(stderr, "%s: cd: %s not set\n", shell->name, name); return 1; } return secure_chdir(new_dir); } -/*! -** Return in previous directory -** -** @param sh shell info -** -** @return return status -*/ -static int cd_minus(struct s_42sh *sh) -{ - if (cd_var(sh, "OLDPWD")) - return 1; - return 0; -} - -/*! -** Change of directory and on error, print good error. -** -** @param path new path -** -** @return error status with error code (0 is good) -*/ static int secure_chdir(const char *path) { - const char *errormsg = ""; char *tmp; - errno = 0; - if (chdir(path)) - { - if (errno == ENOENT) - errormsg = "No such file or directory"; - else if (errno == EACCES) - errormsg = "Permission denied"; - else if (errno == ENAMETOOLONG) - errormsg = "File name too long"; - else if (errno == ENOTDIR) - errormsg = "Not a directory"; - else if (errno == ELOOP) - errormsg = "Too many levels of symbolic links"; - else - assert(0); - fprintf(stderr, "42sh: cd %s: %s\n", path, errormsg); + if (chdir(path)) { + fprintf(stderr, "%s: cd %s: %s\n", shell->name, path, strerror(errno)); return 1; } + //FIXME: getenv return name=val and setenv2 take cut arguments if ((tmp = getenv("PWD"))) - var_setenv("OLDPWD", tmp, !0); - var_setenv("PWD", (tmp = var_getcwd()), !0); - free(tmp); + setenv2("OLDPWD", tmp, !0); + setenv2("PWD", (tmp = getcwd2()), !0); return 0; } diff --git a/src/builtin/builtin_echo.c b/src/builtin/builtin_echo.c index e1f705ff7235eaf1226b1d8a4545a2076b9e65a7..c432a5501163bc12999f7878675730ffa12a641d 100644 --- a/src/builtin/builtin_echo.c +++ b/src/builtin/builtin_echo.c @@ -1,11 +1,11 @@ /* -** builtin_echo.c for 42sh in /goinfre/seblu/builtins +** builtin_echo.c for 42sh ** ** Made by Seblu -** Login +** Login ** ** Started on Tue Mar 14 20:57:07 2006 Seblu -** Last update Wed Apr 12 02:02:07 2006 Seblu +** Last update Wed Nov 15 15:34:18 2006 seblu */ #include @@ -13,64 +13,113 @@ #include #include #include -#include "../main/42sh.h" -#include "../opt/opt.h" +#include "../shell/shell.h" +#include "../shell/option.h" -#include "mem.h" +/* +** ====== +** MACROS +** ====== +*/ #define isoctale(x) (((x) >= '0' && (x) <= '7') ? 1 : 0) -static int builtin_echo_ext(const char *); -static void builtin_echo_ext2(const char **, int *); -static void print_hex(const char **); -static void print_oct(const char **); -static void getoption(char *argv[], int *argp, int *line, int *ext); -static int fisdigit(const int c); -static int fisxdigit(const int c); +/* +** ============ +** DECLARATIONS +** ============ +*/ + +/*! +** Retreive command line option +** +** @param argv argument vector +** @param argp argument position +** @param line line flag +** @param ext extended flag +*/ +static void getoption(char *argv[], int *argp, int *line, int *ext); /*! -** Echo show all element on her line ** -** @param argc number of argument given -** @param argv vector to argument -** @param shopt option structure of shell ** -** @return sucess status +** @param msg +** +** @return if return 0, builtin must quit immediatly, else ok. +*/ +static int builtin_echo_ext(const char *msg); + +/*! +** Print hexa number on stdout a number +** +** @param msg message to print +** @param base base of the number +*/ +static void print_hex(const char **); + +/*! +** Print oct number on stdout a number +** +** @param msg message to print +** @param base base of the number +*/ +static void print_oct(const char **); + +/*! +** Function to say if c is a digit or not. +** It use macro isdigit, but due to epita coding style +** restriction about cast, it's impossible to call +** a macro wrote with int with char, because cast is forbidden +** and macro call, dont have the same right about parameter +** implicit cast (on netBSD) +** +** @param c character +** +** @return if \param c is a digit +*/ +static int fisdigit(const int c); + +/*! +** Function to say if c is a digit or not. +** It use macro isdigit, but due to epita coding style +** restriction about cast, it's impossible to call +** a macro wrote with int with char, because cast is forbidden +** and macro call, dont have the same right about parameter +** implicit cast (on netBSD) +** +** @param c character +** +** @return if \param c is a hexa digit +*/ +static int fisxdigit(const int c); + +/* +** =========== +** DEFINITIONS +** =========== */ -int builtin_echo(char *argv[], struct s_42sh *sh) + +int builtin_echo(char *argv[]) { int argp; int ext = 0; int line = 1; int first; - assert(argv && argv[0] && sh); - ext = opt_isset("xpg_echo", sh->opt); - for (getoption(argv, &argp, &line, &ext), first = argp; argv[argp]; ++argp) - { + assert(argv && argv[0]); + ext = option_is_set(shell->option, "xpg_echo"); + for (getoption(argv, &argp, &line, &ext), first = argp; argv[argp]; ++argp) { if (first != argp) printf(" "); - if (ext) - { - if (!builtin_echo_ext(argv[argp])) - return fflush(stdout); - } - else - printf("%s", argv[argp]); + if (ext && !builtin_echo_ext(argv[argp])) + return fflush(stdout); + printf("%s", argv[argp]); } if (line) printf("\n"); return fflush(stdout); } -/*! -** Retreinve command line option -** -** @param argv argument vector -** @param argp argument position -** @param line line flag -** @param ext extended flag -*/ static void getoption(char *argv[], int *argp, int *line, int *ext) { char *carg; @@ -90,11 +139,6 @@ static void getoption(char *argv[], int *argp, int *line, int *ext) return; } -/*! -** Interpreter for special char -** -** @param msg -*/ static int builtin_echo_ext(const char *msg) { int backed = 0; @@ -118,39 +162,21 @@ static int builtin_echo_ext(const char *msg) putchar('\r'); else if (backed && *msg == 't' && !(backed = 0)) putchar('\t'); + else if (backed && *msg == '\\' && !(backed = 0)) + putchar('\\'); + else if (backed && *msg == 'v' && !(backed = 0)) + putchar('\v'); + else if (backed && fisdigit(*msg) && !(backed = 0)) + print_oct(&msg); + else if (backed && *msg == 'x' && !(backed = 0) && (++msg)) + print_hex(&msg); + else if (backed && !(backed = 0)) + printf("\\%c", *msg); else - builtin_echo_ext2(&msg, &backed); + putchar(*msg); return 1; } -/*! -** End of function builtin_echo_ext due to an stupid norme limitation. -** -** @param msg message to print -** @param backed if a backed char -*/ -static void builtin_echo_ext2(const char **msg, int *backed) -{ - if (*backed && **msg == '\\' && !(*backed = 0)) - putchar('\\'); - else if (*backed && **msg == 'v' && !(*backed = 0)) - putchar('\v'); - else if (*backed && fisdigit(**msg) && !(*backed = 0)) - print_oct(msg); - else if (*backed && **msg == 'x' && !(*backed = 0) && (++*msg)) - print_hex(msg); - else if (*backed && !(backed = 0)) - printf("\\%c", **msg); - else - putchar(**msg); -} - -/*! -** Print hexa number on stdout a number -** -** @param msg message to print -** @param base base of the number -*/ static void print_hex(const char **msg) { char buf[4]; @@ -169,12 +195,6 @@ static void print_hex(const char **msg) printf("%c", (c = n)); } -/*! -** Print oct number on stdout a number -** -** @param msg message to print -** @param base base of the number -*/ static void print_oct(const char **msg) { char buf[5]; @@ -195,35 +215,11 @@ static void print_oct(const char **msg) printf("%c", (c = n)); } -/*! -** Function to say if c is a digit or not. -** It use macro isdigit, but due to epita coding style -** restriction about cast, it's impossible to call -** a macro wrote with int with char, because cast is forbidden -** and macro call, dont have the same right about parameter -** implicit cast (on netBSD) -** -** @param c character -** -** @return if \param c is a digit -*/ static int fisdigit(const int c) { return isdigit(c); } -/*! -** Function to say if c is a digit or not. -** It use macro isdigit, but due to epita coding style -** restriction about cast, it's impossible to call -** a macro wrote with int with char, because cast is forbidden -** and macro call, dont have the same right about parameter -** implicit cast (on netBSD) -** -** @param c character -** -** @return if \param c is a hexa digit -*/ static int fisxdigit(const int c) { return isxdigit(c); diff --git a/src/builtin/builtin_exit.c b/src/builtin/builtin_exit.c index e41bf6556c0ec5ba8a99a51095fb68953beb6321..a07b648c57f62c62a0eb6cddfe73c94edd814c3f 100644 --- a/src/builtin/builtin_exit.c +++ b/src/builtin/builtin_exit.c @@ -5,14 +5,14 @@ ** Login ** ** Started on Sun Nov 12 16:48:50 2006 Seblu -** Last update Sun Nov 12 19:45:36 2006 Seblu +** Last update Wed Nov 15 15:20:00 2006 seblu */ #include #include #include #include -#include "builtin.h" +#include "../shell/shell.h" #include "../common/macro.h" int builtin_exit(char *argv[]) diff --git a/src/builtin/builtin_shopt.c b/src/builtin/builtin_shopt.c index 9a3998e004faab4b19b417d35cf734a5f64f374f..81d51ef95cc1f636bc5ac56ffb72a3eeca32ab45 100644 --- a/src/builtin/builtin_shopt.c +++ b/src/builtin/builtin_shopt.c @@ -1,62 +1,92 @@ /* -** builtin_shopt.c for 42sh in /goinfre/seblu/42sh/src +** builtin_shopt.c for 42sh ** ** Made by Seblu -** Login +** Login ** ** Started on Wed Mar 22 16:27:35 2006 Seblu -** Last update Tue Apr 11 00:24:22 2006 Seblu +** Last update Wed Nov 15 15:18:32 2006 seblu */ #include #include #include #include "builtin.h" -#include "../main/42sh.h" -#include "../opt/opt.h" +#include "../shell/option.h" +#include "../shell/shell.h" -#include "mem.h" +/* +** ============ +** DECLARATIONS +** ============ +*/ +/*! +** Retreinve command line option +** +** @param argv argument vector +** @param argp argument position +** @param line line flag +** @param ext extended flag +*/ static void getoption(char *argv[], int *argp, int opts[2]); -static int mutator_opt(char *argv[], int *argp, int opts[2], struct s_42sh *sh); -static int show_opt(char *argv[], int *argp, int opts[2], struct s_42sh *sh); -static int show_all_opt(int quiet, struct s_42sh *sh); /*! -** This builtin change local setting of the shell -** opts[0] == set or unset -** opts[1] == quiet mode +** Sun or unset an option ** -** @param argv argument vector -** @param sh shell data +** @param argv arg vector +** @param argp cur pos +** @param opts argline opts +** +** @return builtin status +*/ +static int mutator_opt(char *argv[], int *argp, int opts[2]); + +/*! +** Show info about shell opts +** +** @param argv arg vector +** @param argp cur pos +** @param opts argline opts ** -** @return success status +** @return builtin status */ -int builtin_shopt(char *argv[], struct s_42sh *sh) +static int show_opt(char *argv[], int *argp, int opts[2]); + +/*! +** Show all options +** +** @param quiet silent showing +** +** @return return status +*/ +static int show_all_opt(int quiet); + +/* +** =========== +** DEFINITIONS +** =========== +*/ + +int builtin_shopt(char *argv[]) { - int opts[2]; int argp = 1; + int opts[2]; + // opts[0] == set or unset mode + // opts[1] == quiet mode - assert(argv && argv[0] && sh); + assert(argv && argv[0]); opts[0] = -1; opts[1] = 0; getoption(argv, &argp, opts); if (opts[0] == -1 && !argv[argp]) - return show_all_opt(opts[1], sh); + return show_all_opt(opts[1]); else if (opts[0] == -1 && argv[argp]) - return show_opt(argv, &argp, opts, sh); + return show_opt(argv, &argp, opts); else - return mutator_opt(argv, &argp, opts, sh); + return mutator_opt(argv, &argp, opts); } -/*! -** Retreinve command line option -** -** @param argv argument vector -** @param argp argument position -** @param line line flag -** @param ext extended flag -*/ static void getoption(char *argv[], int *argp, int opts[2]) { for (; argv[*argp]; ++*argp) @@ -70,64 +100,38 @@ static void getoption(char *argv[], int *argp, int opts[2]) break; } -/*! -** Sun or unset an option -** -** @param argv arg vector -** @param argp cur pos -** @param opts argline opts -** @param sh struct info -** -** @return builtin status -*/ static int mutator_opt(char *argv[], int *argp, - int opts[2], - struct s_42sh *sh) + int opts[2]) { int ret = 0; - for (; argv[*argp]; ++*argp) - { - if (opt_isset(argv[*argp], sh->opt) == -1) - { - fprintf(stderr, "42sh: shopt: %s: invalid shell option name\n", - argv[*argp]); + for (; argv[*argp]; ++*argp) { + if (option_is_set(shell->option, argv[*argp]) == -1) { + fprintf(stderr, "%s: shopt: %s: invalid shell option name\n", + shell->name, argv[*argp]); ret = 1; continue; } if (opts[0]) - opt_set(argv[*argp], sh->opt); + option_set(shell->option, argv[*argp]); else - opt_unset(argv[*argp], sh->opt); + option_unset(shell->option, argv[*argp]); } return ret; } -/*! -** Show info about shell opts -** -** @param argv arg vector -** @param argp cur pos -** @param opts argline opts -** @param sh struct info -** -** @return builtin status -*/ static int show_opt(char *argv[], int *argp, - int opts[2], - struct s_42sh *sh) + int opts[2]) { int ret = 0; int isset = 0; - for (; argv[*argp]; ++*argp) - { - if ((isset = opt_isset(argv[*argp], sh->opt)) == -1) - { - fprintf(stderr, "42sh: shopt: %s: invalid shell option name\n", - argv[*argp]); + for (; argv[*argp]; ++*argp) { + if ((isset = option_is_set(shell->option, argv[*argp])) == -1) { + fprintf(stderr, "%s: shopt: %s: invalid shell option name\n", + shell->name, argv[*argp]); ret = 1; continue; } @@ -139,14 +143,7 @@ static int show_opt(char *argv[], return ret; } -/*! -** Show all options -** -** @param quiet silent showing -** -** @return return status -*/ -static int show_all_opt(int quiet, struct s_42sh *sh) +static int show_all_opt(int quiet) { const char **opts; register int i; @@ -155,6 +152,7 @@ static int show_all_opt(int quiet, struct s_42sh *sh) return 0; opts = opt_get(); for (i = 0; opts[i]; ++i) - printf("%-15s %s\n", opts[i], (opt_isset(opts[i], sh->opt)) ? "yes" : "no"); + printf("%-15s %s\n", opts[i], + (option_is_set(shell->option, opts[i])) ? "yes" : "no"); return 0; } diff --git a/src/builtin/builtin_unalias.c b/src/builtin/builtin_unalias.c new file mode 100644 index 0000000000000000000000000000000000000000..65c073c4138526522dc1737dc8fee91a038cee00 --- /dev/null +++ b/src/builtin/builtin_unalias.c @@ -0,0 +1,20 @@ +/* +** builtin_unalias.c for 42sh +** +** Made by seblu +** Login +** +** Started on Thu Nov 16 17:18:24 2006 seblu +** Last update Thu Nov 16 17:49:49 2006 seblu +*/ + +#include +#include "builtin.h" + +int builtin_unalias(char *argv[]) +{ + assert(argv && argv[0]); + assert(0); + argv = argv; + return 0; +} diff --git a/src/common/function.h b/src/common/function.h index 6d7396c8d03d541bcf2a2af81479cb1036b91085..5fa821fff01b01c2f85fba146e9e3b5a52eb7db6 100644 --- a/src/common/function.h +++ b/src/common/function.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 30 03:59:48 2006 Seblu -** Last update Tue Nov 14 15:36:14 2006 seblu +** Last update Wed Nov 15 10:34:19 2006 seblu */ #ifndef FUNCTION_H_ @@ -81,6 +81,8 @@ char **strvectoradd(char **vector, char *str); */ char *getcwd2(void); +# define setenv setenv2 + /*! ** Add a name and value to the current environment ** @@ -94,6 +96,8 @@ int setenv2(char *name, char *value, int overwrite); +# define unsetenv unsetenv2 + /*! ** Remove from environment a variable. ** @warning Don't use unsetenv ! diff --git a/src/exec/exec.h b/src/exec/exec.h index 0510e360fe2ac27cfaf47bf7a42159b09971fdda..3acaab58cf2365ea318fb4ad504cb0e2ff9fa695 100644 --- a/src/exec/exec.h +++ b/src/exec/exec.h @@ -5,29 +5,29 @@ ** Login ** ** Started on Sun Mar 30 16:02:07 2006 Seblu -** Last update Sun Nov 12 16:41:42 2006 Seblu +** Last update Thu Nov 16 16:06:41 2006 seblu */ #ifndef EXEC_H_ # define EXEC_H_ # include -# include # include "../ast/ast.h" # include "../shell/shell.h" +# define DEBUG_EXEC 0 + void exec_node(s_ast_node *node); + +void exec_cmd(s_cmd_node *cmd); void exec_and(s_bin_node *node); void exec_or(s_bin_node *node); void exec_bang(s_bin_node *node); void exec_if(s_if_node *node); void exec_red(s_red_node *red); void exec_while(s_while_node *node); - -/* FIXME */ - -/* void exec_for(struct s_for *node, struct s_42sh *sh); */ -/* void exec_case(struct s_case *node, struct s_42sh *sh); */ -/* void exec_funcdec(struct s_funcdec *node, struct s_42sh *sh); */ +void exec_sep(s_bin_node *node); +void exec_sepand(s_bin_node *node); +void exec_funcdec(s_funcdec_node *node); #endif diff --git a/src/exec/exec_and.c b/src/exec/exec_and.c index 89eab82e816bfab4fe6c975cb20197f6998d3277..0bdbf4239ff1ee5246392838b137ddb765961fff 100644 --- a/src/exec/exec_and.c +++ b/src/exec/exec_and.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sat Mar 25 15:27:20 2006 Seblu -** Last update Sun Nov 12 13:40:37 2006 seblu +** Last update Thu Nov 16 15:02:58 2006 seblu */ #include "exec.h" @@ -14,7 +14,12 @@ void exec_and(s_bin_node *node) { assert(node); exec_node(node->lhs); - //FIXME: error with chained "or" and "and" if (!shell->status) exec_node(node->rhs); + else { + for (; node->rhs->type == T_AND; node = &node->rhs->body.child_and) + ; //do nothing + if (node->rhs->type == T_OR) + exec_node(node->rhs->body.child_or.rhs); + } } diff --git a/src/exec/exec_cmd.c b/src/exec/exec_cmd.c index be6f226bfb7c17dd9fafb7af08c4a7c3ce8ebfc0..9b5d77406d66ca8f7687735826a4db6bc4c6b741 100644 --- a/src/exec/exec_cmd.c +++ b/src/exec/exec_cmd.c @@ -5,40 +5,38 @@ ** Login ** ** Started on Sat Apr 8 07:38:48 2006 Seblu -** Last update Tue Nov 14 13:50:59 2006 seblu +** Last update Thu Nov 16 17:15:37 2006 seblu */ -#define DEBUG_EXEC 0 - #include #include #include #include #include #include -#include #include -#include -#include "../shell/shell.h" -#include "../ast/ast.h" #include "exec.h" #include "../builtin/builtin.h" +#include "../common/function.h" -/* #define rederror(prompt) do { perror(prompt); return 0; } while (0) */ - -/* struct s_reds_context */ -/* { */ -/* int old; */ -/* int save; */ -/* int end; */ -/* }; */ - +/* +** ============ +** DECLARATIONS +** ============ +*/ -static int exec_forked(s_cmd_node *cmd); +static int exec_program(s_cmd_node *cmd); +static void exec_function(char **argv); static void exec_argv(char **argv); static void exec_prefix(char **prefix, int glob); static void cmd_debugger(s_cmd_node *cmd); +/* +** =========== +** DEFINITIONS +** =========== +*/ + void exec_cmd(s_cmd_node *cmd) { assert(cmd); @@ -49,19 +47,21 @@ void exec_cmd(s_cmd_node *cmd) if (cmd->prefix) exec_prefix(cmd->prefix, 0); return; } - if (is_a_builtin(cmd->argv[0])) - shell->status = exec_builtin(cmd); + if (is_a_function(shell->func, cmd->argv[0])) + exec_function(cmd->argv); + else if (is_a_builtin(cmd->argv[0])) + shell->status = get_builtin(cmd->argv[0])(cmd->argv); else - shell->status = exec_forked(cmd); + shell->status = exec_program(cmd); } -static int exec_forked(s_cmd_node *cmd) +static int exec_program(s_cmd_node *cmd) { pid_t pid; int status; if ((pid = fork()) == -1) { - fprintf(stderr, "%s: Cannot fork\n", shell->name); + fprintf(stderr, "%s: Cannot fork.\n", shell->name); return ERROR_FORK; } if (pid) { @@ -71,7 +71,9 @@ static int exec_forked(s_cmd_node *cmd) if (cmd->prefix) exec_prefix(cmd->prefix, 1); exec_argv(cmd->argv); + //never reach assert(0); + return 1; } static void exec_argv(char **argv) @@ -80,9 +82,9 @@ static void exec_argv(char **argv) execvp(argv[0], argv); if (errno == ENOENT) if (strchr(argv[0], '/') == NULL) - fprintf(stderr, "%s: %s: command not found\n", shell->name, argv[0]); + fprintf(stderr, "%s: %s: command not found.\n", shell->name, argv[0]); else - fprintf(stderr, "%s: %s: No such file or directory\n", + fprintf(stderr, "%s: %s: No such file or directory.\n", shell->name, argv[0]); else perror(shell->name); @@ -99,12 +101,18 @@ static void exec_prefix(char **prefix, int glob) assert(0); *value++ = 0; if (glob) - var_setenv(prefix[i], value, !0); + setenv2(prefix[i], value, !0); else - var_set(sh->vars, prefix[i], value, !0); + var_set(shell->var, prefix[i], value, !0); } } +static void exec_function(char **argv) +{ + assert(argv && argv[0]); + //FIXME: add arguments transmission here + exec_node(func_get(shell->func, argv[0])); +} /* /\*! */ /* ** Execute a command in a pipeline. This call preserve for too many system call fork */ @@ -130,133 +138,6 @@ static void exec_prefix(char **prefix, int glob) /* } */ /* } */ -/* /\*! */ -/* ** 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); */ -/* } */ - - - - - -/* /\*! */ -/* ** 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 ** @@ -277,6 +158,6 @@ static void cmd_debugger(s_cmd_node *cmd) /* 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"); } diff --git a/src/exec/exec_funcdec.c b/src/exec/exec_funcdec.c new file mode 100644 index 0000000000000000000000000000000000000000..d90a09fd8f46a707df9f778f067d76d6539f5666 --- /dev/null +++ b/src/exec/exec_funcdec.c @@ -0,0 +1,19 @@ +/* +** exec_funcdec.c for 42sh +** +** Made by seblu +** Login +** +** Started on Thu Nov 16 16:06:00 2006 seblu +** Last update Thu Nov 16 17:04:48 2006 seblu +*/ + +#include "exec.h" +#include "../shell/func.h" + +void exec_funcdec(s_funcdec_node *node) +{ + func_add(shell->func, node->name, node->body); + node->body = NULL; + node->name = NULL; +} diff --git a/src/exec/exec_node.c b/src/exec/exec_node.c index b12500742321452fe49a13c3baf6db189f1971c8..44cdf53ce044ae0e2749c52bde83f2965687e01f 100644 --- a/src/exec/exec_node.c +++ b/src/exec/exec_node.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sat Mar 25 14:51:09 2006 Seblu -** Last update Sun Nov 12 16:43:18 2006 Seblu +** Last update Thu Nov 16 16:48:52 2006 seblu */ #include "exec.h" @@ -14,19 +14,19 @@ void exec_node(s_ast_node *node) { assert(node); switch (node->type) { - case T_SEP: break; - case T_SEPAND: break; - case T_CMD: break; + case T_SEP: exec_sep(&node->body.child_sep);break; + case T_SEPAND: exec_sepand(&node->body.child_sepand);break; + case T_CMD: exec_cmd(&node->body.child_cmd); break; case T_RED: exec_red(&node->body.child_red); break; - case T_PIPE: break; +/* case T_PIPE: exec_pipe(&node->body.child_pipe); break; */ case T_AND: exec_and(&node->body.child_and); break; case T_OR: exec_or(&node->body.child_or); break; case T_IF: exec_if(&node->body.child_if); break; case T_WHILE: exec_while(&node->body.child_while); break; case T_BANG: exec_bang(&node->body.child_bang); break; - case T_SUBSHELL: break; - case T_FUNCDEC: break; - case T_CASE: break; + case T_SUBSHELL: assert(0); break; + case T_FUNCDEC: exec_funcdec(&node->body.child_funcdec); break; + case T_CASE: assert(0); break; default: assert(0); } } diff --git a/src/exec/exec_or.c b/src/exec/exec_or.c index 6b6587b65977bae8994a33d9d6849cbd3fcb681c..216145a5eec0de5fe2ec63675dcff46898491b32 100644 --- a/src/exec/exec_or.c +++ b/src/exec/exec_or.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sat Mar 25 15:27:20 2006 Seblu -** Last update Sun Nov 12 13:40:45 2006 seblu +** Last update Thu Nov 16 15:07:07 2006 seblu */ #include "exec.h" @@ -14,7 +14,12 @@ void exec_or(s_bin_node *node) { assert(node); exec_node(node->lhs); - //FIXME: error with chained "or" and "and" if (shell->status) exec_node(node->rhs); + else { + for (; node->rhs->type == T_OR; node = &node->rhs->body.child_or) + ; //do nothing + if (node->rhs->type == T_AND) + exec_node(node->rhs->body.child_and.rhs); + } } diff --git a/src/exec/exec_red.c b/src/exec/exec_red.c index dc2716baf0103a6951e2c5103039b5c1030a2783..a8910d076a0e028a27e563de6bb9173fa15a5b42 100644 --- a/src/exec/exec_red.c +++ b/src/exec/exec_red.c @@ -5,12 +5,199 @@ ** Login ** ** Started on Sun Nov 12 16:39:51 2006 Seblu -** Last update Sun Nov 12 16:44:02 2006 Seblu +** Last update Thu Nov 16 15:52:08 2006 seblu */ +#include +#include +#include +#include #include "exec.h" -void exec_red(s_red_node *red) +/* +** =========== +** MACROS +** =========== +*/ + +#define rederror(file, msg) do { fprintf(stderr, "%s: %s: %s.\n", \ + shell->name, file, msg); return 1; } while (0) + +#define is_open_read(flags) (((flags) & 0x3) == O_RDONLY || \ + ((flags) & 0x2) == O_RDWR) + +#define is_open_write(flags) (((flags) & 0x3) == O_WRONLY || \ + ((flags) & 0x2) == O_RDWR) + +/* +** ============ +** DECLARATIONS +** ============ +*/ + +typedef struct red_context { + int old; //old fd number + int save; //save of old fd +} s_red_context; + +/*! +** Save the current red context +** +** @param reds red node +** +** @return a struct that contains all current redirection context +*/ +static s_red_context *save_red_context(s_red_node *reds); + +/*! +** Restore a previous redirection context and free it +** +** @param context context to restore +*/ +static void restore_red_context(s_red_context *context); + +/*! +** Apply redirections +** +** @param reds red node +** +** @return success status +*/ +static int apply_red(s_red_node *reds); + +/*! +** Retrieve an fd from a word +** +** @param txt fd in string +** +** @return -1 if fail, -2 for close fd else fd +*/ +static int get_filedes(const char *txt); + +/* +** =========== +** DEFINITIONS +** =========== +*/ + +void exec_red(s_red_node *red) +{ + s_red_context *context; + assert(red); + //FIXME: expansion on red here + context = save_red_context(red); + shell->status = apply_red(red); + if (!shell->status) + exec_node(red->mhs); + restore_red_context(context); +} + +static s_red_context *save_red_context(s_red_node *reds) +{ + s_red_context *context; + register size_t i; + + secmalloc(context, (reds->size + 1) * sizeof (s_red_context)); + for (i = 0; i < reds->size; ++i) { + context[i].old = reds->fd[i]; + context[i].save = dup(reds->fd[i]); + } + context[i].old = -1; + return context; +} + +static void restore_red_context(s_red_context *context) +{ + for (register int i = 0; context[i].old != - 1; ++i) + dup2(context[i].save, context[i].old); + free(context); +} + +static int apply_red(s_red_node *reds) +{ + int fd; + + assert(reds); + for (size_t i = 0; i < reds->size; ++i) { + switch (reds->type[i]) { + case R_LESS: // < + if ((fd = open(reds->word[i], O_RDONLY)) == -1) + rederror(reds->word[i], strerror(errno)); + dup2(fd, reds->fd[i]); + close(fd); + break; + case R_GREAT: // > + if (option_is_set(shell->option, "noclobber") && + !access(reds->word[i], F_OK)) + rederror(reds->word[i], "cannot overwrite existing file"); + case R_CLOBBER: // >| + if ((fd = open(reds->word[i], O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) + rederror(reds->word[i], strerror(errno)); + dup2(fd, reds->fd[i]); + close(fd); + break; + case R_DGREAT: // >> + if ((fd = open(reds->word[i], O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1) + rederror(reds->word[i], strerror(errno)); + dup2(fd, reds->fd[i]); + close(fd); + break; + case R_GREATAND: // >& + case R_LESSAND: // <& + fd = get_filedes(reds->word[i]); + int flags; + if (fd == -1) + rederror(reds->word[i], "ambiguous redirect"); + else if (fd == -2 && close(reds->fd[i])) + rederror(reds->word[i], strerror(errno)); + else if ((flags = fcntl(fd, F_GETFL)) == -1) + rederror(reds->word[i], strerror(errno)); + if (reds->type[i] == R_GREATAND && !is_open_write(flags)) + rederror(reds->word[i], "fd not open for writing"); + if (reds->type[i] == R_LESSAND && !is_open_read(flags)) + rederror(reds->word[i], "fd not open for reading"); + dup2(fd, reds->fd[i]); + break; + case R_LESSGREAT: // <> + assert(0); + //FIXME + break; + case R_DLESS: // << + assert(0); + /* 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_DLESSDASH: // <<- + assert(0); + //FIXME + break; + default: + fprintf(stderr, "%s: Invalid redirection.\n", shell->name); + assert(0); + return 1; + } + } + return 0; +} + +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) + return -1; + return fd; } diff --git a/src/parser/alias.c b/src/parser/alias.c deleted file mode 100644 index 53cd3706344853deae2d1eeb9c0a291fb93bba2a..0000000000000000000000000000000000000000 --- a/src/parser/alias.c +++ /dev/null @@ -1,73 +0,0 @@ -/* -** alias.c for 42sh -** -** Made by Seblu -** Login -** -** Started on Wed Aug 23 00:39:17 2006 Seblu -** Last update Tue Nov 14 15:34:32 2006 seblu -*/ - -#include -#include "alias.h" -#include "../common/macro.h" - -static size_t step = 5; - -s_alias *alias_init(void) -{ - s_alias *new; - - secmalloc(new, sizeof (s_alias)); - new->size = step; - new->pos = 0; - new->db = NULL; - return new; -} - -void alias_add(s_alias *aliases, const char *name, const char *value) -{ - s_alias_item *new; - int freeplace = 0; - size_t index; - - //check if already exist and if free place exist - for (register int i = 0; aliases && aliases->db[i]; ++i) - if (!strcmp(aliases->db[i]->name, name)) { - free(aliases->db[i]->value); - aliases->db[i]->value = strdup(value); - return; - } - else if (!freeplace && *aliases->db[i]->name == 0) - index = i; - //if a place is free, fill it - if (freeplace) { - aliases->db[index]->name = strdup(name); - aliases->db[index]->value = strdup(value); - return; - } - //create a new one - secmalloc(new, sizeof (s_alias_item)); - new->name = strdup(name); - new->value = strdup(value); - //add a new alias if not find - if (aliases->pos >= aliases->size) { - aliases->size += step; - secrealloc(aliases->db, aliases->db, aliases->size * sizeof (s_alias_item)); - } - aliases->db[aliases->pos] = new; - ++aliases->pos; -} - -int alias_remove(s_alias *aliases, const char *name) -{ - //find alias index - for (register int i = 0; aliases && aliases->db[i]; ++i) - if (!strcmp(aliases->db[i]->name, name)) { - free(aliases->db[i]->name); - free(aliases->db[i]->value); - aliases->db[i]->name = ""; - return 1; - } - return 0; -} diff --git a/src/parser/parser.c b/src/parser/parser.c index 71856857d81c06146da91cb00fa9dbb64784e256..df8b22746d008b808615481b081034bc70d23bff 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 2 00:56:07 2006 Seblu -** Last update Tue Nov 14 15:38:06 2006 seblu +** Last update Thu Nov 16 15:52:31 2006 seblu */ @@ -15,6 +15,7 @@ #include #include #include +#include #include "parser.h" #include "../common/macro.h" #include "../common/function.h" diff --git a/src/shell/alias.c b/src/shell/alias.c new file mode 100644 index 0000000000000000000000000000000000000000..d0d2a9f173b6348c8994f52b4d0c71a2eb8b8820 --- /dev/null +++ b/src/shell/alias.c @@ -0,0 +1,67 @@ +/* +** alias.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Wed Aug 23 00:39:17 2006 Seblu +** Last update Thu Nov 16 18:58:49 2006 seblu +*/ + +#include +#include +#include "alias.h" +#include "../common/macro.h" + +/* +** =========== +** DEFINITIONS +** =========== +*/ + +s_alias *alias_init(void) +{ + s_alias *new; + + secmalloc(new, sizeof (s_alias)); + new->count = 0; + new->size = ALIAS_DEFAULT_SIZE; + secmalloc(new->table, new->size * sizeof (s_alias_item)); + return new; +} + +int alias_add(s_alias *alias, char *name, char *value) +{ + int ret; + + assert(alias && name); + ret = alias_del(alias, name); + ++alias->count; + if (alias->size < alias->count) { + alias->size += ALIAS_PADDING; + secrealloc(alias->table, alias->table, alias->size * sizeof (s_alias_item)); + } + alias->table[alias->count - 1].name = name; + alias->table[alias->count - 1].value = value; + return ret; +} + +int alias_del(s_alias *alias, const char *name) +{ + register size_t i; + + assert(alias && name); + for (i = 0; i < alias->count; ++i) + if (!strcmp(name, alias->table[i].name)) + break; + if (i >= alias->count) + return 0; + free(alias->table[i].name); + free(alias->table[i].value); + alias->table[i] = alias->table[--alias->count]; + if (alias->size - alias->count > 2 * ALIAS_PADDING) { + alias->size -= ALIAS_PADDING; + secrealloc(alias->table, alias->table, alias->size * sizeof (s_alias_item)); + } + return 1; +} diff --git a/src/parser/alias.h b/src/shell/alias.h similarity index 68% rename from src/parser/alias.h rename to src/shell/alias.h index 637244faf9d770c73a969fc06802c646d5e4c4e3..7e6df72bae658cea5cb5d9445e16bcc0cfd11be2 100644 --- a/src/parser/alias.h +++ b/src/shell/alias.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 23 00:32:09 2006 Seblu -** Last update Tue Nov 14 15:32:55 2006 seblu +** Last update Thu Nov 16 17:53:46 2006 seblu */ #ifndef ALIAS_H_ @@ -13,6 +13,11 @@ # include +enum { + ALIAS_DEFAULT_SIZE = 5, + ALIAS_PADDING = 5 +}; + typedef struct alias_item { char *name; @@ -22,8 +27,8 @@ typedef struct alias_item typedef struct alias { size_t size; - size_t pos; - s_alias_item **db; + size_t count; + s_alias_item *table; } s_alias; /*! @@ -40,7 +45,7 @@ s_alias *alias_init(void); ** @param name new alias name ** @param value new alias value */ -void alias_add(s_alias *aliases, const char *name, const char *value); +int alias_add(s_alias *alias, char *name, char *value); /*! ** Remove an alias into an alias database @@ -48,8 +53,8 @@ void alias_add(s_alias *aliases, const char *name, const char *value); ** @param aliases alias database ** @param name alias name to remove ** -** @return true, if alias was found in database, else false +** @return true, if alias was delete from database, else false */ -int alias_remove(s_alias *aliases, const char *name); +int alias_del(s_alias *alias, const char *name); #endif diff --git a/src/shell/func.c b/src/shell/func.c index 1d0372fd18b49a9423e4372fb35635b8a1298f91..96702b2f31c76909b801d68345bdce91fb41eae4 100644 --- a/src/shell/func.c +++ b/src/shell/func.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Tue Nov 14 14:52:39 2006 seblu -** Last update Tue Nov 14 15:59:57 2006 seblu +** Last update Thu Nov 16 17:40:11 2006 seblu */ /* @@ -16,6 +16,7 @@ #include #include "func.h" +#include "../ast/ast.h" #include "../common/macro.h" /* @@ -24,9 +25,9 @@ ** =========== */ -s_func *func_init(void) +s_func *func_init(void) { - s_func *new; + s_func *new; secmalloc(new, sizeof (s_func)); new->count = 0; @@ -34,3 +35,57 @@ s_func *func_init(void) secmalloc(new->table, new->size * sizeof (s_func_item)); return new; } + +int is_a_function(s_func *func, const char *name) +{ + assert(func && name); + for (register size_t i = 0; i < func->count; ++i) + if (!strcmp(name, func->table[i].name)) + return 1; + return 0; +} + +int func_add(s_func *func, char *name, s_ast_node *body) +{ + int ret; + + assert(func && name); + ret = func_del(func, name); + ++func->count; + if (func->size < func->count) { + func->size += FUNC_PADDING; + secrealloc(func->table, func->table, func->size * sizeof (s_func_item)); + } + func->table[func->count - 1].name = name; + func->table[func->count - 1].body = body; + return ret; +} + +int func_del(s_func *func, const char *name) +{ + register size_t i; + + assert(func && name); + for (i = 0; i < func->count; ++i) + if (!strcmp(name, func->table[i].name)) + break; + if (i >= func->count) + return 0; + free(func->table[i].name); + ast_destruct(func->table[i].body); + func->table[i] = func->table[--func->count]; + if (func->size - func->count > 2 * FUNC_PADDING) { + func->size -= FUNC_PADDING; + secrealloc(func->table, func->table, func->size * sizeof (s_func_item)); + } + return 1; +} + +s_ast_node *func_get(s_func *func, const char *name) +{ + assert(func && name); + for (register size_t i = 0; i < func->count; ++i) + if (!strcmp(name, func->table[i].name)) + return func->table[i].body; + return NULL; +} diff --git a/src/shell/func.h b/src/shell/func.h index 4f1c8f00a484d3ab003b3c9211762165c853f9cb..926ff165196fba15ea12c03171e16061656e0813 100644 --- a/src/shell/func.h +++ b/src/shell/func.h @@ -5,17 +5,19 @@ ** Login ** ** Started on Tue Nov 14 14:52:22 2006 seblu -** Last update Tue Nov 14 15:59:32 2006 seblu +** Last update Thu Nov 16 17:02:27 2006 seblu */ #ifndef FUNC_H_ # define FUNC_H_ # include -# include # include "../ast/ast.h" -enum { FUNC_DEFAULT_SIZE = 5 }; +enum { + FUNC_DEFAULT_SIZE = 5, + FUNC_PADDING = 5 +}; typedef struct func_item { @@ -37,10 +39,48 @@ typedef struct func */ s_func *func_init(void); -/* int func_add(char *, struct s_ast *, struct s_func **); */ -/* int func_del(const char *, struct s_func **); */ -/* int func_exec(const char *, struct s_42sh *); */ -/* void func_clean(struct s_func **); */ -/* struct s_ast *func_get(const char *, struct s_func **); */ +/*! +** Return if @var name is a function. +** +** @param func func struct +** @param name function name +** +** @return boolean existance +*/ +int is_a_function(s_func *func, const char *name); + +/*! +** Add a function. @var name and @var body are not copied. +** Not free/modify it after adding function. +** Return a boolean which explain if function @var name +** has been deleted before insertion. +** +** @param func func struct +** @param name func name +** @param body func body +** +** @return an boolean already exist function information +*/ +int func_add(s_func *func, char *name, s_ast_node *body); + +/*! +** Delete a function and destroy is AST. +** +** @param func func struct +** @param name func name to deleted +** +** @return Boolean delete success +*/ +int func_del(s_func *func, const char *name); + +/*! +** Return the function body of a function. +** +** @param func func struct +** @param name func name +** +** @return ast node to corresponding to the function +*/ +s_ast_node *func_get(s_func *func, const char *name); #endif diff --git a/src/shell/option.c b/src/shell/option.c index 5c352b398f69153bbb06940174938aae6e162340..34325d1db185a0d98a1d421cf6d1e5a4995d07f0 100644 --- a/src/shell/option.c +++ b/src/shell/option.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Tue Mar 21 19:00:38 2006 Seblu -** Last update Tue Nov 14 20:30:23 2006 seblu +** Last update Wed Nov 15 13:35:24 2006 seblu */ /* @@ -28,6 +28,7 @@ static const char *opts_table[OPTION_COUNT] = { "expand_aliases", "ast_print", "readline", + "noclobber", }; /* @@ -80,7 +81,7 @@ int option_unset(s_option *shopt, const char *name) return 0; } -int option_isset(const s_option *shopt, const char *name) +int option_is_set(const s_option *shopt, const char *name) { register int i; diff --git a/src/shell/option.h b/src/shell/option.h index 7a5664899b1bbf686b21a8390336ad67b79e5987..85e6638c269265d999129eed23604b4e39d10186 100644 --- a/src/shell/option.h +++ b/src/shell/option.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Tue Mar 21 18:50:03 2006 Seblu -** Last update Tue Nov 14 15:29:08 2006 seblu +** Last update Wed Nov 15 13:35:32 2006 seblu */ #ifndef OPTION_H_ @@ -13,7 +13,7 @@ #define DEBUG_OPTION 0 -enum { OPTION_COUNT = 9 }; +enum { OPTION_COUNT = 10 }; typedef struct option { @@ -69,7 +69,7 @@ int option_unset(s_option *shopt, const char *name); ** ** @return 0 if unset, 1 if set and -1 if not exist */ -int option_isset(const s_option *shopt, const char *name); +int option_is_set(const s_option *shopt, const char *name); /*! ** Return a list of know opt diff --git a/src/shell/shell.c b/src/shell/shell.c index 88465b4eded96a2292938affac2d9cfba88f73ca..e2df561ab79e3a4d97c1888b3b62255152d0998e 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Mon Apr 10 23:57:28 2006 Seblu -** Last update Tue Nov 14 15:46:38 2006 seblu +** Last update Wed Nov 15 14:14:05 2006 seblu */ #include @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) option_set_default(shell->option); // parse argv for user options getoptions(shell->option, argc, argv); - //FIXME: set PWD et OLDPWD variable + //FIXME: set shell env variables (eg. PWD, OLDPWD) // shell parser init parser = parser_init(STDIN_FILENO); // parse and execute stdin stream @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) continue; else if (parser->error) return ERROR_PARSE; - if (option_isset(shell->option, "ast_print")) + if (option_is_set(shell->option, "ast_print")) ast_print(ast, NULL); if (ast) exec_node(ast); diff --git a/src/shell/shell.h b/src/shell/shell.h index 43d45f1bcb0ab3054268e77aa43df939816c5f15..ebd4e6d8d5f17b7a45a914358d4571d58435a6a0 100644 --- a/src/shell/shell.h +++ b/src/shell/shell.h @@ -5,16 +5,14 @@ ** Login ** ** Started on Sun Jul 16 20:03:53 2006 Seblu -** Last update Tue Nov 14 15:30:52 2006 seblu +** Last update Thu Nov 16 16:54:53 2006 seblu */ #ifndef SHELL_H_ # define SHELL_H_ -# include -# include # include "../common/constant.h" -# include "../parser/alias.h" +# include "alias.h" # include "var.h" # include "option.h" # include "func.h" diff --git a/src/shell/var.c b/src/shell/var.c index ef857904211ccf63bfa513263b22f4b3f9acb8cc..76be55457f70e870a0800cc98ace75b2c266cca8 100644 --- a/src/shell/var.c +++ b/src/shell/var.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Tue Nov 14 13:55:46 2006 seblu -** Last update Tue Nov 14 16:25:06 2006 seblu +** Last update Thu Nov 16 15:14:34 2006 seblu */ #include @@ -45,10 +45,9 @@ const char *var_get(const s_var *var, const char *name) void var_set(s_var *var, char *name, char *value, - int env, int overwrite) { - assert(0); var = var; name = value; env = overwrite; + assert(0); var = var; name = value; overwrite = overwrite; /* size_t i; */ /* int pos = -1; */ @@ -76,6 +75,7 @@ void var_set(s_var *var, int var_unset(s_var *var, const char *name) { assert(var && name); + var = var; name = name; /* if (getenv(name)) { */ /* var_unsetenv(name); */ /* return 0; */ diff --git a/src/shell/var.h b/src/shell/var.h index 3a9564154e8e684fadbac4e3500b27dd13c121a1..7dfd7270aaa7cd742d9eb9c02dc4190fb33dbc40 100644 --- a/src/shell/var.h +++ b/src/shell/var.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Tue Nov 14 13:54:14 2006 seblu -** Last update Tue Nov 14 15:26:09 2006 seblu +** Last update Wed Nov 15 10:36:09 2006 seblu */ #ifndef VAR_H_ @@ -55,7 +55,6 @@ const char *var_get(const s_var *var, const char *name); void var_set(s_var *var, char *name, char *value, - int env, int overwrite); /*! diff --git a/test/exec/and_1.sh b/test/exec/and_1.sh new file mode 100644 index 0000000000000000000000000000000000000000..68631f494bb353f54eda6eed80dda9bafe694772 --- /dev/null +++ b/test/exec/and_1.sh @@ -0,0 +1 @@ +{ echo toto; false; } && echo titi && echo tutu && echo mumu || { echo ca bande; exit 2; } diff --git a/test/exec/or_1.sh b/test/exec/or_1.sh new file mode 100644 index 0000000000000000000000000000000000000000..e77314ea6438f1b8571bf1ed935b396e528698ec --- /dev/null +++ b/test/exec/or_1.sh @@ -0,0 +1 @@ +{ echo toto; false; } || echo titi || echo tutu || echo mumu || { echo ca bande; exit 2; } && echo "ouais"