Commit de22dd53 authored by Seblu's avatar Seblu
Browse files

work on execution

work on variables
work on functions
parent cf642cb2
......@@ -21,8 +21,10 @@ bin_PROGRAMS=42sh
src/builtin/builtin.c \
src/builtin/builtin_exit.c \
src/common/basename.c \
src/common/common.h \
src/common/constant.h \
src/common/env.c \
src/common/function.h \
src/common/getcwd2.c \
src/common/isdigitstr.c \
src/common/macro.h \
src/common/strmerge.c \
......@@ -39,21 +41,24 @@ bin_PROGRAMS=42sh
src/exec/exec_sep.c \
src/exec/exec_sepand.c \
src/exec/exec_while.c \
src/parser/alias.h \
src/parser/alias.c \
src/parser/getline.h \
src/parser/alias.h \
src/parser/getline.c \
src/parser/parser.h \
src/parser/getline.h \
src/parser/parser.c \
src/parser/parser.h \
src/parser/lexer.c \
src/shell/func.c \
src/shell/func.h \
src/shell/getoptions.c \
src/shell/option.h \
src/shell/option.c \
src/shell/option.h \
src/shell/shell.c \
src/shell/shell.h \
src/shell/shell_entry.c \
src/shell/shell_init.c \
src/shell/shell_destroy.c \
src/shell/prompt.c
src/shell/prompt.c \
src/shell/var.c \
src/shell/var.h
CLEANFILES= *~ \#*\#
......
42sh
This program was written by Sebastien Luttringer aka Seblu
......@@ -98,16 +98,6 @@ AC_ARG_WITH([noerror],
]
)
AC_ARG_WITH([dynamic],
[AS_HELP_STRING([--with-dynamic], [Compiling with dynamic libraries])],
[dnl action-if-given
dynamic=true
],
[dnl action-if-not-given
dynamic=false
]
)
AC_ARG_WITH([debug],
[AS_HELP_STRING([--with-debug], [use -g and don't use -DNDEBUG -O3])],
[dnl action-if-given
......@@ -125,7 +115,7 @@ AC_ARG_WITH([efence],
CFLAGS="$CFLAGS -include stdlib.h -include efence.h"
],
[dnl action-if-not-given
test "$dynamic" = "true" || LDFLAGS="$LDFLAGS -static"
true
]
)
......@@ -141,4 +131,4 @@ AC_CONFIG_FILES([
Makefile
])
AC_OUTPUT
\ No newline at end of file
AC_OUTPUT
......@@ -5,11 +5,11 @@
** Login <seblu@epita.fr>
**
** Started on Thu Aug 3 05:29:46 2006 Seblu
** Last update Sat Aug 19 01:57:49 2006 Seblu
** Last update Tue Nov 14 15:37:34 2006 seblu
*/
#include <string.h>
#include "common.h"
#include "function.h"
char *basename(const char *path)
{
......
/*
** env.c for 42sh
**
** Made by seblu
** Login <seblu@epita.fr>
**
** Started on Tue Nov 14 14:38:42 2006 seblu
** Last update Tue Nov 14 15:37:46 2006 seblu
*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include "function.h"
int setenv2(char *name,
char *value,
int overwrite)
{
extern char **environ;
char *buf;
char **env = environ;
size_t len;
assert(name && value && env);
len = strlen(name);
if (!overwrite)
for (; *env; ++env)
if (!strncmp(name, *env, len) && (*env)[len] == '=')
return 1;
buf = strmerge(3, name, "=", value);
return !putenv(buf) ? 0 : 2;
}
int unsetenv2(const char *name)
{
extern char **environ;
size_t len;
char **ep = environ;
char **dp = ep;
if (name == NULL || *name == '\0' || strchr(name, '=') != NULL)
{
errno = EINVAL;
return -1;
}
len = strlen(name);
for (; *ep; ++ep)
{
if (!strncmp(*ep, name, len) && (*ep)[len] == '=')
{
dp = ep;
do
dp[0] = dp[1];
while (++dp, *dp);
}
}
return 0;
}
/*
** common.h for 42sh
** function.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:59:48 2006 Seblu
** Last update Wed Oct 11 16:56:07 2006 seblu
** Last update Tue Nov 14 15:36:14 2006 seblu
*/
#ifndef COMMON_H_
# define COMMON_H_
#ifndef FUNCTION_H_
# define FUNCTION_H_
/*!
** Merge strings
......@@ -74,4 +74,34 @@ int isdigitstr(const char *str);
*/
char **strvectoradd(char **vector, char *str);
/*!
** Return the current working directory in a malloced string.
**
** @return the current working directory
*/
char *getcwd2(void);
/*!
** Add a name and value to the current environment
**
** @param name variable name
** @param value variable value
** @param overwrite boolean which tell if overwrite a existing value
**
** @return boolean success
*/
int setenv2(char *name,
char *value,
int overwrite);
/*!
** Remove from environment a variable.
** @warning Don't use unsetenv !
**
** @param name env variable to remove
**
** @return boolean success
*/
int unsetenv2(const char *name);
#endif
/*
** getcwd2.c for 42sh
**
** Made by seblu
** Login <seblu@epita.fr>
**
** Started on Tue Nov 14 14:20:08 2006 seblu
** Last update Tue Nov 14 14:23:39 2006 seblu
*/
#include <unistd.h>
#include <limits.h>
#include "macro.h"
char *getcwd2(void)
{
char *get;
const size_t BUF_SIZE = PATH_MAX * sizeof (char);
secmalloc(get, BUF_SIZE);
return getcwd(get, BUF_SIZE);
}
......@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Sat Apr 8 07:38:48 2006 Seblu
** Last update Sun Nov 12 04:04:09 2006 seblu
** Last update Tue Nov 14 13:50:59 2006 seblu
*/
#define DEBUG_EXEC 0
......@@ -19,295 +19,250 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "../main/42sh.h"
#include "../shell/shell.h"
#include "../ast/ast.h"
#include "execution.h"
#include "exec.h"
#include "../builtin/builtin.h"
#include "../var/var.h"
#include "../globbing/quoting.h"
#include "../history/history.h"
#include "../expand/expand.h"
/* #define rederror(prompt) do { perror(prompt); return 0; } while (0) */
#define rederror(prompt) do { perror(prompt); return 0; } while (0)
/* struct s_reds_context */
/* { */
/* int old; */
/* int save; */
/* int end; */
/* }; */
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);
static int exec_forked(s_cmd_node *cmd);
static void exec_argv(char **argv);
static void exec_prefix(char **prefix, int glob);
static void cmd_debugger(s_cmd_node *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)
void exec_cmd(s_cmd_node *cmd)
{
struct s_reds_context *context;
assert(cmd && sh);
assert(cmd);
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);
cmd_debugger(cmd);
//FIXME: expansions here
if (!cmd->argv) {
if (cmd->prefix) exec_prefix(cmd->prefix, 0);
return;
}
if (is_a_builtin(cmd->argv[0]))
shell->status = exec_builtin(cmd);
else
create_fork(cmd, sh);
shell->status = exec_forked(cmd);
}
/*!
** 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)
static int exec_forked(s_cmd_node *cmd)
{
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);
}
}
pid_t pid;
int status;
/*!
** 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 = fork()) == -1) {
fprintf(stderr, "%s: Cannot fork\n", shell->name);
return ERROR_FORK;
}
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);
if (pid) {
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
if (cmd->prefix)
exec_prefix(cmd->prefix, 1);
exec_argv(cmd->argv);
assert(0);
}
/*!
** Certify a correct changement of context
**
** @param cmd Execute a command
*/
static void launch_cmd(struct s_cmd *cmd)
static void exec_argv(char **argv)
{
execvp(cmd->argv[0], cmd->argv);
assert(argv && argv[0]);
execvp(argv[0], argv);
if (errno == ENOENT)
if (strchr(cmd->argv[0], '/') == NULL)
fprintf(stderr, "42sh: %s: command not found\n", cmd->argv[0]);
if (strchr(argv[0], '/') == NULL)
fprintf(stderr, "%s: %s: command not found\n", shell->name, argv[0]);
else
fprintf(stderr, "42sh: %s: No such file or directory\n", cmd->argv[0]);
fprintf(stderr, "%s: %s: No such file or directory\n",
shell->name, argv[0]);
else
perror("42sh");
perror(shell->name);
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)
static void exec_prefix(char **prefix, int glob)
{
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);
assert(prefix);
for (int 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;
}
/* /\*! */
/* ** 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->prefix, 1, sh); */
/* launch_cmd(cmd); */
/* } */
/* } */
/*!
** 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;
/* /\*! */
/* ** 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; */
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;
}
/* 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; */