Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
epita
42sh
Commits
de22dd53
Commit
de22dd53
authored
Nov 14, 2006
by
Seblu
Browse files
work on execution
work on variables work on functions
parent
cf642cb2
Changes
23
Hide whitespace changes
Inline
Side-by-side
Makefile.am
View file @
de22dd53
...
...
@@ -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
=
*
~
\#
*
\#
...
...
README
0 → 100644
View file @
de22dd53
42sh
This program was written by Sebastien Luttringer aka Seblu
configure.ac
View file @
de22dd53
...
...
@@ -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
src/common/basename.c
View file @
de22dd53
...
...
@@ -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
S
eblu
** Last update
Tue Nov 14 15:37:34
2006
s
eblu
*/
#include <string.h>
#include "
comm
on.h"
#include "
functi
on.h"
char
*
basename
(
const
char
*
path
)
{
...
...
src/common/env.c
0 → 100644
View file @
de22dd53
/*
** 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
;
}
src/common/
comm
on.h
→
src/common/
functi
on.h
View file @
de22dd53
/*
**
comm
on.h for 42sh
**
functi
on.h for 42sh
**
** Made by Seblu
** Login <seblu@epita.fr>
**
** Started on Sun Jul 30 03:59:48 2006 Seblu
** Last update
Wed Oct
1
1
1
6:56:07
2006 seblu
** Last update
Tue Nov
1
4
1
5:36:14
2006 seblu
*/
#ifndef
COMM
ON_H_
# define
COMM
ON_H_
#ifndef
FUNCTI
ON_H_
# define
FUNCTI
ON_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
src/common/getcwd2.c
0 → 100644
View file @
de22dd53
/*
** 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
);
}
src/exec/exec_cmd.c
View file @
de22dd53
...
...
@@ -5,7 +5,7 @@
** Login <seblu@epita.fr>
**
** Started on Sat Apr 8 07:38:48 2006 Seblu
** Last update
Sun
Nov 1
2 04:04:0
9 2006 seblu
** Last update
Tue
Nov 1
4 13:50:5
9 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 "exec
ution
.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
_fork
ed
(
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); */
/* } */
/* } */
/*
!
**
R
et
rieve 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
;
/*
/\*! */
/*
**
S
et
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; */