Compare commits
138 Commits
hugo_pipes
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ac5efeaed | ||
|
|
19c3d51726 | ||
|
|
dfe3f6977a | ||
|
|
fd72d63dd6 | ||
|
|
69adb1cf2f | ||
|
|
9bffb99b30 | ||
|
|
9e8d92e0b5 | ||
|
|
523f560eab | ||
|
|
b51535cdbc | ||
|
|
638dbbaf9c | ||
|
|
54c9df31e4 | ||
|
|
5a39470290 | ||
|
|
e4c4589d3c | ||
|
|
80917cae7c | ||
|
|
8ed97346f7 | ||
|
|
6a9b7bae1b | ||
|
|
e138e6550b | ||
|
|
0cfb13595c | ||
|
|
11d2f36307 | ||
|
|
b8281e329c | ||
|
|
7de89b43b1 | ||
|
|
8959166804 | ||
|
|
0a64977cdc | ||
|
|
59a43ea1cc | ||
|
|
49099a0abd | ||
|
|
0e520ef31e | ||
|
|
fa474c86ab | ||
|
|
afbb1cd2e0 | ||
|
|
fa71189132 | ||
|
|
36de7bf150 | ||
|
|
59f0b7603b | ||
|
|
e5852579ef | ||
|
|
81cc6fbff6 | ||
|
|
06f1987ae4 | ||
|
|
20c71bccbb | ||
|
|
f53969cd45 | ||
|
|
5a0a237aaa | ||
|
|
e5f033694b | ||
|
|
5c1d8f527c | ||
|
|
9c660d4f92 | ||
|
|
a7de843dc1 | ||
|
|
465c4de21e | ||
|
|
82f0362323 | ||
|
|
d3d55386d9 | ||
|
|
9322ec9ec9 | ||
|
|
592bcb4e93 | ||
|
|
f7d37fadb6 | ||
|
|
73feaf0230 | ||
|
|
34da9678dc | ||
|
|
322d8d5f09 | ||
|
|
cee6a8962b | ||
|
|
bcc82aabaf | ||
|
|
8125e43065 | ||
|
|
312c90539b | ||
|
|
8a7611da92 | ||
|
|
caa733e14a | ||
|
|
200e043a8c | ||
|
|
2d85c34b98 | ||
|
|
b7b3cec6e0 | ||
|
|
66183ab441 | ||
|
|
c3a9035622 | ||
|
|
27c00a78a0 | ||
|
|
2eed0f2d45 | ||
|
|
fb1974dd3b | ||
|
|
d710f5ef68 | ||
|
|
b3f74c4179 | ||
|
|
b08da252de | ||
|
|
025ef76c01 | ||
|
|
ffd06c4b95 | ||
|
|
b265e8475a | ||
|
|
33f4878f36 | ||
|
|
cb5c2dcb30 | ||
|
|
aa7efdab15 | ||
|
|
5b3e566b25 | ||
|
|
3baf91afb3 | ||
|
|
843b6d84c5 | ||
|
|
07e98c7cf8 | ||
|
|
b9d7ebb3cb | ||
|
|
18d430c5cb | ||
|
|
3465354af5 | ||
|
|
32eab95d48 | ||
|
|
ac11eee947 | ||
|
|
ef3e91be13 | ||
|
|
80410e6d81 | ||
|
|
ef12d6ba4b | ||
|
|
0b6d8cf127 | ||
|
|
74ee526d57 | ||
|
|
7c65dcd897 | ||
|
|
0bd9dcb3bb | ||
|
|
c11c61ec5e | ||
|
|
91d5a0d14c | ||
|
|
e715c09de1 | ||
|
|
860c4daaf0 | ||
|
|
6a4b1f54b2 | ||
|
|
26993144cc | ||
|
|
965cf99ca5 | ||
|
|
493ac0bd40 | ||
|
|
f70ee4bae0 | ||
|
|
140549db00 | ||
|
|
36766501ba | ||
|
|
57c271b9e2 | ||
|
|
bb77de0588 | ||
|
|
402196b9a9 | ||
|
|
66b48dc99d | ||
|
|
1e682f796d | ||
|
|
106af37b58 | ||
|
|
86707f9fc6 | ||
|
|
47ae67ed14 | ||
|
|
d65a701186 | ||
|
|
0ae84abb14 | ||
|
|
0a5c7545c1 | ||
|
|
0a33916c75 | ||
|
|
5a98927eff | ||
|
|
a6959ac1f8 | ||
|
|
03acb65880 | ||
|
|
533128af89 | ||
|
|
bb44760e2b | ||
|
|
f93825ee59 | ||
|
|
07f458c875 | ||
|
|
b9fc6a9bc4 | ||
|
|
d4151227b3 | ||
|
|
27ac62bddc | ||
|
|
a926a817da | ||
|
|
22d4bbfdd0 | ||
|
|
c0ef57499a | ||
|
|
ab2aa509df | ||
|
|
698dcbe1ed | ||
|
|
118e2e5bef | ||
|
|
0292425bc1 | ||
|
|
58ef5a4a03 | ||
|
|
75987a117e | ||
|
|
15bc4d2158 | ||
|
|
b1b8a61921 | ||
|
|
62955af5b8 | ||
|
|
815cedb8ca | ||
|
|
906074d2cb | ||
|
|
39de10e001 | ||
|
|
1054f3d6ff |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.o
|
||||
*.swp
|
||||
*.out
|
||||
@@ -9,7 +10,11 @@
|
||||
*.dSYM
|
||||
.vscode
|
||||
*.lnk
|
||||
*.zip
|
||||
memo
|
||||
memo.txt
|
||||
minishell
|
||||
*.zip
|
||||
arg_test
|
||||
osef_temp
|
||||
env_var_test
|
||||
memo_local
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "libft"]
|
||||
path = libft
|
||||
url = git@bitbucket.org:LuckyLaszlo/libft.git
|
||||
[submodule "minishell_tests"]
|
||||
path = minishell_tests
|
||||
url = git@bitbucket.org:LuckyLaszlo/minishell_tests.git
|
||||
|
||||
35
Makefile
35
Makefile
@@ -2,10 +2,18 @@ NAME = minishell
|
||||
|
||||
CC = clang
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -g
|
||||
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) # add -g
|
||||
|
||||
VPATH = $(DIR_SRCS)
|
||||
DIR_SRCS = srcs srcs/builtins
|
||||
DIR_SRCS = srcs \
|
||||
srcs/init \
|
||||
srcs/builtins \
|
||||
srcs/lexing \
|
||||
srcs/parsing srcs/parsing/valid_syntax \
|
||||
srcs/parsing/expansions srcs/parsing/redirections \
|
||||
srcs/exec \
|
||||
srcs/generic \
|
||||
srcs/misc \
|
||||
|
||||
INCLUDES = -I$(HEADERS_D) -I$(LIBFT_D)
|
||||
|
||||
@@ -21,10 +29,25 @@ LIBS = -L $(LIBFT_D) -lft \
|
||||
LIBFT_D = ./libft
|
||||
LIBFT = $(LIBFT_D)/libft.a
|
||||
|
||||
SRCS = main.c init.c free.c generic.c \
|
||||
env.c exit.c \
|
||||
pipes_hugo.c \
|
||||
parser_hugo.c
|
||||
SRCS = main.c \
|
||||
shell_loop.c shell_script.c \
|
||||
init.c init_prompt.c init_readline.c init_shlvl.c open_script_file.c \
|
||||
retrieve_path.c \
|
||||
free.c \
|
||||
signals.c error_wrappers.c last_exit_status.c \
|
||||
lexing.c fill_token.c check_operators.c \
|
||||
parsing.c create_pipeline.c \
|
||||
valid_syntax.c valid_pipeline.c valid_command.c rules_command.c valid_io_redirect.c \
|
||||
expansions.c \
|
||||
expand_token.c content_expand.c content_copy.c \
|
||||
rejoin_after_expand.c new_token_for_each_field.c \
|
||||
redirections.c here_doc.c \
|
||||
exec_cmd_line.c pipeline.c \
|
||||
find_access.c subshell_exec.c subshell_wait.c simple_cmd_builtin.c \
|
||||
cd.c pwd.c export.c unset.c exit.c env.c echo.c \
|
||||
ft_split_quotes.c ft_strdup_quotes.c \
|
||||
ft_strjoinfree.c ft_lst_func.c ft_isinset_str.c ft_is_posix_name.c \
|
||||
ft_getenv.c ft_free_null.c ft_2d_arr_func.c \
|
||||
|
||||
DIR_OBJS = builds
|
||||
OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o)
|
||||
|
||||
518
README.md
518
README.md
@@ -1,518 +0,0 @@
|
||||
## sommaire :
|
||||
---
|
||||
- [1. todo list :](#markdown-header-1-todo-list)
|
||||
- [2. parsing :](#markdown-header-2-parsing)
|
||||
- [2.1. methode arbre binaire :](#markdown-header-21-methode-arbre-binaire)
|
||||
- [3. gerer les quotes et la separation des arguments :](#markdown-header-3-gerer-les-quotes-et-la-separation-des-arguments)
|
||||
- [3.1. tentative methode 1 :](#markdown-header-31-tentative-methode-1)
|
||||
- [3.1.1. pseudo code :](#markdown-header-311-pseudo-code)
|
||||
- [3.1.2. application :](#markdown-header-312-application)
|
||||
- [3.1.3. erreur :](#markdown-header-313-erreur)
|
||||
- [3.2. tentative methode 2 :](#markdown-header-32-tentative-methode-2)
|
||||
- [3.2.1. deroulement :](#markdown-header-321-deroulement)
|
||||
- [3.2.2. application :](#markdown-header-322-application)
|
||||
- [3.3. comportement reel chelou :](#markdown-header-33-comportement-reel-chelou)
|
||||
- [4. notes :](#markdown-header-4-notes)
|
||||
|
||||
## 1. todo list :
|
||||
---
|
||||
|
||||
- **global features :**
|
||||
- `prompt` *show a prompt*
|
||||
- `history` **? the command history ?**
|
||||
- `binaries` *fetch and launch the right executable*
|
||||
- `'` `"` `;` `\` **? don't interpret special characters and unclosed quotes ?**
|
||||
- **pipes :** [video vulgarisation](https://www.youtube.com/watch?v=bKzonnwoR2I)
|
||||
- `|` *pipes*
|
||||
- **expensions :**
|
||||
- `$` *variable expension*
|
||||
- `$?` *exit return of last executed process* [ressource stackoverflow](https://stackoverflow.com/questions/7248031/meaning-of-dollar-question-mark-in-shell-scripts)
|
||||
- **quotes :** [ressource](https://linuxhandbook.com/quotes-in-bash/)
|
||||
- `'` *(ignore any special characters)*
|
||||
- `"` *(ignore any special characters except '$')*
|
||||
- **redirections & heredocs :** [ressource](https://www.gnu.org/software/bash/manual/html_node/Redirections.html) / [heredocs for readability](https://www.techrepublic.com/article/use-heredoc-in-shell-scripts/)
|
||||
- `<` *redirect input*
|
||||
- `>` *redirect output*
|
||||
- `<<` *read input until empty line --* **? doesn't update history ?**
|
||||
- `>>` *redirect and append*
|
||||
- **signals :**
|
||||
- `^C` *close process*
|
||||
- `^D` *exit minishell*
|
||||
- `^\` *do nothing*
|
||||
- **builtins (can't be executed in child process) :**
|
||||
- `cd <relative path>`
|
||||
- `cd <absolute path>`
|
||||
- `pwd`
|
||||
- `export`
|
||||
- `unset`
|
||||
- ~~`exit`~~
|
||||
- **builtins (don't need to be) :** [source](https://git.42l.fr/Fabien/minishell)
|
||||
- `env`
|
||||
- ~~`echo`~~
|
||||
- `echo -n`
|
||||
- **autres :**
|
||||
- `termcap` [man](https://www.gnu.org/software/termutils/manual/termcap-1.3/html_chapter/termcap_toc.html)
|
||||
- `readline` [man](https://tiswww.case.edu/php/chet/readline/rltop.html) / [second source](https://tiswww.case.edu/php/chet/readline/README)
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
## 2. lexer (lexique analyser :
|
||||
---
|
||||
|
||||
[tutorial on fork and exec](https://www.youtube.com/watch?v=O1UOWScmqxg)
|
||||
[wait for all childs to terminate](https://stackoverflow.com/questions/19461744/how-to-make-parent-wait-for-all-child-processes-to-finish)
|
||||
[close pipes in child AND parents](https://stackoverflow.com/questions/33884291/pipes-dup2-and-exec)
|
||||
[how a shell works](https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/Book/Chapter5-WritingYourOwnShell.pdf)
|
||||
|
||||
### 2.1 methode arbre binaire :
|
||||
|
||||
[transformer arbre normal en arbre binaire](https://fr.wikipedia.org/wiki/Arbre_binaire#Transformation_d'un_arbre_quelconque_en_un_arbre_binaire)
|
||||
|
||||
```text
|
||||
arbre lexical :
|
||||
all
|
||||
. pipes
|
||||
. . redirections (program function or file)
|
||||
. . . arguments (nom arg arg arg ...)
|
||||
. . . .
|
||||
EXEMPLE : . .
|
||||
[< file ./prgrm 'arg1 '$VARIABLE" arg3" | grep "word.$EXTENSION" | wc -l > file]
|
||||
. [< file ./prgrm 'arg1 'arg2" arg3"]
|
||||
. . [file]
|
||||
. . [./prgrm 'arg1 'arg2" arg3"]
|
||||
. . . [./prgrm]
|
||||
. . . ['arg1 'arg2" arg3"]
|
||||
. [grep "word.md"]
|
||||
. . . [grep]
|
||||
. . . ["word.md"]
|
||||
. [wc -l > file]
|
||||
. . [file]
|
||||
. . [wc -l]
|
||||
. . . [wc]
|
||||
. . . [-l]
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
> export TEST=""
|
||||
> ./test_argv $TEST foo
|
||||
argv[0] : [./test_argv]
|
||||
argv[1] : [foo]
|
||||
|
||||
> export TEST=" bar "
|
||||
> ./test_argv foo"$TEST"foo
|
||||
argv[0] : [./test_argv]
|
||||
argv[1] : [foo bar foo]
|
||||
|
||||
> export TEST="bar"
|
||||
> ./test_argv "foo "$TEST" foo"
|
||||
argv[0] : [./test_argv]
|
||||
argv[1] : [foo bar foo]
|
||||
|
||||
## 3. gerer les quotes et la separation des arguments :
|
||||
---
|
||||
|
||||
### 3.1 tentative methode 1 :
|
||||
|
||||
#### 3.1.1 pseudo code :
|
||||
```text
|
||||
q = 0 // first quote
|
||||
c = 0 // count
|
||||
i = 0
|
||||
while (str[i])
|
||||
{
|
||||
if (str[i] == ')
|
||||
{
|
||||
if (q == ')
|
||||
{
|
||||
c--;
|
||||
if (c == 0)
|
||||
{
|
||||
q = 0;
|
||||
create_new_substr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c++;
|
||||
if (q == 0)
|
||||
q = ';
|
||||
}
|
||||
}
|
||||
if (str[i] == ")
|
||||
{
|
||||
if (q == ")
|
||||
{
|
||||
c--;
|
||||
if (c == 0)
|
||||
{
|
||||
q = 0;
|
||||
create_new_substr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c++;
|
||||
if (q == 0)
|
||||
q = ";
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
#### 3.1.2 application :
|
||||
```text
|
||||
['][a][r][g][1][ ]['][a][r][g][2]["][ ][a][r][g][3]["]
|
||||
c = 0 . . . . . . . . . . . . . . . . . .
|
||||
c = 1 . . . . . . . . . . . . . . . . . str[i] == ' ; q == 0 c == 0 -> c++; q = '
|
||||
c = . 1 . . . . . . . . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . 1 . . . . . . . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . 1 . . . . . . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . 1 . . . . . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . 1 . . . . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . 0 . . . . . . . . . . . str[i] == ' ; q == ' c == 1 -> c--; q = 0;
|
||||
arg1 = [a][r][g][1][ ]
|
||||
c = . . . . . . . 0 . . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . 0 . . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . 0 . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . 0 . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . . 1 . . . . . . str[i] == " ; q != " c == 0 -> c++; q = ";
|
||||
arg2 = [a][r][g][2]
|
||||
c = . . . . . . . . . . . . 1 . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . . . . 1 . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . . . . . 1 . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . . . . . . 1 . . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . . . . . . . 1 . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . . . . . . . . . 0 str[i] == " ; q == " c == 1 -> c--; q = 0;
|
||||
arg3 = [ ][a][r][g][3]
|
||||
|
||||
['][a]["][r]['][g][']["][1][']
|
||||
c = 0 . . . . . . . . . .
|
||||
c = 1 . . . . . . . . . str[i] == ' ; q == 0 c == 0 -> c++; q = '
|
||||
c = . 1 . . . . . . . . str[i] != ' | " ; ->
|
||||
c = . . 2 . . . . . . . str[i] == " ; q != " c == 1 -> c++;
|
||||
c = . . . 2 . . . . . . str[i] != ' | " ; ->
|
||||
c = . . . . 3 . . . . . str[i] == ' | " ; q == ' c == 2 -> c++;
|
||||
c = . . . . . 3 . . . . str[i] != ' | " ; ->
|
||||
c = . . . . . . 2 . . . str[i] == ' ; q == ' c == 3 -> c--; q = 0;
|
||||
c = . . . . . . . 1 . . str[i] == " ; q != " c == 2 ->
|
||||
ERROR ...
|
||||
c = . . . . . . . . 1 . str[i] != ' | " ; ->
|
||||
c = . . . . . . . . . 0 str[i] != ' | " ; ->
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
#### 3.1.3 erreur :
|
||||
-> comment le programme sait que cette fois il doit decrementer "c" ?
|
||||
en retenant dans l'ordre toutes les dernieres valeurs de "q" !
|
||||
|
||||
-> donc plutot partir sur une recursive
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
### 3.2 tentative methode 2 :
|
||||
|
||||
#### 3.2.1 deroulement :
|
||||
```text
|
||||
.--------------------------------------------.
|
||||
: .--------------------------------------. :
|
||||
: : .--------------------------------. : :
|
||||
: : : .--------. .--------. : : :
|
||||
: : : .--. : .--. : : .--. : : : :
|
||||
'__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
|
||||
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
|
||||
```
|
||||
-> identifier les paires de quotes ou dquotes
|
||||
-> piège :
|
||||
```text
|
||||
| |
|
||||
.--. .--. v v .--.
|
||||
'__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
|
||||
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
|
||||
```
|
||||
|
||||
0. envoyer une copie de la str dans une fonction
|
||||
1. chercher la premiere pair
|
||||
2. l'effacer
|
||||
3. recommencer en boucle
|
||||
4. stop quand la premier quote a trouvé sa paire
|
||||
5. renvoyer l'emplacement de la pair
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
#### 3.2.2 application :
|
||||
```text
|
||||
.--.
|
||||
1 : '__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
|
||||
|
||||
.--.
|
||||
2 : '__"__'________"__'__'__"__"__'__'__"__'__"__'
|
||||
|
||||
.--------.
|
||||
3 : '__"__'________"________"__"__'__'__"__'__"__'
|
||||
|
||||
.--.
|
||||
4 : '__"__'____________________"__'__'__"__'__"__'
|
||||
|
||||
.--------.
|
||||
5 : '__"__'____________________"________"__'__"__'
|
||||
|
||||
.--------------------------------.
|
||||
6 : '__"__'________________________________'__"__'
|
||||
|
||||
.--------------------------------------.
|
||||
7 : '__"______________________________________"__'
|
||||
|
||||
.--------------------------------------------.
|
||||
8 : '____________________________________________'
|
||||
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
### 3.3 comportement reel chelou :
|
||||
```text
|
||||
echo "_"
|
||||
_
|
||||
|
||||
echo "_'_'_"
|
||||
_'_'_
|
||||
|
||||
echo "_'_"_"_'_"
|
||||
_'___'_
|
||||
|
||||
echo "_'_"_'_'_"_'_"
|
||||
_'_____'_
|
||||
|
||||
echo "_'_"_'_"_"_'_"_'_"
|
||||
_'___"_"___'_
|
||||
|
||||
echo "_'_"_"_"_"_'_"
|
||||
_'_____'_
|
||||
|
||||
echo "_'_"_'_"_"_"_"_'_"_'_"
|
||||
_'___"_"_"_"___'_
|
||||
|
||||
echo "_'_"_'_"_'_'_"_'_"_'_"
|
||||
_'___"___"___'_
|
||||
|
||||
echo "_'_"_'_"_'_"_"_'_"_'_"_'_"
|
||||
_'___"_____"___'_
|
||||
|
||||
echo "_'_"_'_"_'_"_'_'_"_'_"_'_"_'_"
|
||||
_'___"___'_'___"___'_
|
||||
|
||||
echo "_'_"_'_"_'_"_'_"_"_'_"_'_"_'_"_'_"
|
||||
_'___"___'___'___"___'_
|
||||
|
||||
echo "_'_"_'_"_'_"_'_"_'_'_"_'_"_'_"_'_"_'_"
|
||||
_'___"___'_____'___"___'_
|
||||
|
||||
echo "_'_"_'_"_'_"_'_"_'_"_"_'_"_'_"_'_"_'_"_'_"
|
||||
_'___"___'___"_"___'___"___'_
|
||||
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
## 4. notes :
|
||||
---
|
||||
|
||||
**idea about malloc protection :**
|
||||
|
||||
have them(malloc and similar) done in a specific function that would check their return and accordingly exit the program or continue
|
||||
|
||||
-> so that it can be done in one line
|
||||
|
||||
void calloc_or_exit(int num, int size);
|
||||
|
||||
and possibly give it a pointer to a function that will clean before exit
|
||||
|
||||
void calloc_or_exit(int num, int size, void (*f)(void *ptr), void *ptr);
|
||||
|
||||
---
|
||||
|
||||
Ordre Interpreteur :
|
||||
1) Couper les mots (comment faire ? je ne vois pas comment gerer ce genre de bordel ci dessous)
|
||||
```
|
||||
shell@prompt> ./arg_test 'mot1 '$NAME" mot2"
|
||||
argc = 2
|
||||
argv[0] = |./arg_test|
|
||||
argv[1] = |mot1 Tour-Lemdows10 mot2|
|
||||
shell@prompt>
|
||||
```
|
||||
2) $ - Env Vars Expand. if $VAR not set, expand to nothing("").
|
||||
Dont save it as "" argument for fonctions, just delete.
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
--------------
|
||||
|
||||
Commandes dans variables d'env fonctionne :
|
||||
```
|
||||
shell@prompt> export VAR_TEST="echo"
|
||||
shell@prompt> $VAR_TEST "string :)"
|
||||
string :)
|
||||
shell@prompt>
|
||||
```
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
--------------
|
||||
|
||||
l'expension des variables dans des variables est fait au moment de export(),
|
||||
donc pas de recursivité infini et de prise de tête au moment de l'interpretation.
|
||||
Il suffit de faire "une passe" pour dévelloper les variables,
|
||||
aucun besoin de refaire des passes succesives pour d'éventuels nouvelles variables aprés dévellopement :
|
||||
|
||||
```
|
||||
export :
|
||||
export VAR_TEST="test $NAME"
|
||||
dans l'env :
|
||||
NAME="Tour-Lemdows10"
|
||||
VAR_TEST="test Tour-Lemdows10"
|
||||
|
||||
export :
|
||||
export NAME="Un nouveau nom"
|
||||
dans l'env :
|
||||
NAME="Un nouveau nom"
|
||||
VAR_TEST="test Tour-Lemdows10"
|
||||
```
|
||||
```
|
||||
export :
|
||||
export VAR_TEST="test $VAR_TEST"
|
||||
dans l'env :
|
||||
VAR_TEST="test test Tour-Lemdows10"
|
||||
|
||||
export :
|
||||
export VAR_TEST="test $VAR_TEST"
|
||||
dans l'env :
|
||||
VAR_TEST="test test test Tour-Lemdows10"
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
Tests pour Hugo, pour illustrer les pipes simultanés :
|
||||
```
|
||||
sleep 3 ; sleep 3 ; sleep 3 ; sleep 3
|
||||
sleep 3 | sleep 3 | sleep 3 | sleep 3
|
||||
|
||||
sleep 5 ; ls | wc -l
|
||||
sleep 5 | ls | wc -l
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
argv passé à execv(), telle quelle ou aprés avoir trouvé le PATH ?
|
||||
exemple, si j'apelle "cat file.txt", dans un shell genre bash/zsh,
|
||||
la commande cat recoit t'elle :
|
||||
```
|
||||
argv[0] == "cat"
|
||||
argv[1] == "file.txt"
|
||||
```
|
||||
OU
|
||||
```
|
||||
argv[0] == "/bin/cat"
|
||||
argv[1] == "file.txt"
|
||||
```
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
A test sur bash et minishell :
|
||||
|
||||
echo "phrase quelquonque" > file1 > file2 > file3
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
Pour les builtins dans une commande simple :
|
||||
1) detecter la commande builtin
|
||||
2) Ne pas fork() et execv().
|
||||
A la place, chercher la fonction aproprié dans un tableau contenant les pointeurs vers les fonctions builtins.
|
||||
Puis appeler la fonction dans le genre : builtin(ft_arrlen(cmd->argv), cmd->argv, &c).
|
||||
|
||||
|
||||
Pour les builtins dans une commande complexe (pipes, redirections, here doc, ...) :
|
||||
1) detecter la commande builtin
|
||||
2) fork()
|
||||
3) Ne pas execv().
|
||||
A la place, chercher la fonction aproprié dans un tableau contenant les pointeurs vers les fonctions builtins.
|
||||
Puis appeler la fonction dans le genre : builtin(ft_arrlen(cmd->argv), cmd->argv, &c).
|
||||
4) aprés la fin de la commande, free toute la mémoire du sous_processus, puis quitter le sous_processus en renvoyant le return de la commande builtin.
|
||||
par exemple comme ça :
|
||||
free_exit(&c, builtin(ft_arrlen(cmd->argv), cmd->argv, &c))
|
||||
|
||||
|
||||
Peut-être faire un champ "void *builtin_command" dans une struct "cmd" pour contenir l'adresse de la fonction builtin.
|
||||
```
|
||||
typedef struct s_cmd
|
||||
{
|
||||
char **argv;
|
||||
pid_t pid;
|
||||
void *builtin_command;
|
||||
} t_cmd;
|
||||
```
|
||||
Si la commande n'est pas builtin
|
||||
|
||||
cmd->builtin_command == NULL.
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
tester comment ce comporte minishell aprés le crash d'une commande (message sigfault comme dans bash ? Autres ?)
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
Implementer les exit status dans les builtins
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
EDIT : Aprés reflexion et verification, ça semble en effet le mieux a faire.
|
||||
En l'etat le return de la derniere fonction marche correctement, j'ai verifier pas de problemes.
|
||||
Si le child est deja fini avant l'apelle de wait, ça return quand même.
|
||||
Cependant, pour optimiser la liberation des resources dés que possible,
|
||||
il semble plus logique de liberer les sous_processus dés qu'ils ont terminés,
|
||||
et donc, pas nécessairement dans l'ordre de la pipeline.
|
||||
Donc, un waitpid() sur la derniere commande pour sauvegarder le retour,
|
||||
puis wait() pour les autres, l'ordre n'ayant plus d'importance.
|
||||
|
||||
Revoir le wait() de mon pipex. Il n'est peut être pas correct.
|
||||
En effet, j'attend que le premier process se ferme avec waitpid(), puis le deuxiéme, le troisiéme, ...
|
||||
Mais en faite, il vaudrait peut être mieux attendre qu'un sous process QUELQUONQUE se ferme, puis le suivant, et le suivant, ...
|
||||
|
||||
Vu le fonctionnement des pipes, je crois que ce n'est pas toujours la premiere commande qui ce termine en premier,
|
||||
et donc, qu'il ne faudrait pas attendre la fin de la premiere commande en particulier,
|
||||
mais d'une commande QUELQUONQUE avec wait() plutot que waitpid().
|
||||
|
||||
IDÉE :
|
||||
Attendre avec waitpid() la derniere commande pour obtenir son status, puis wait() en boucle les autres commandes,
|
||||
et enfin renvoyer le status.
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
-------------------
|
||||
|
||||
Faire des test avec
|
||||
|
||||
"env -i ./minishell"
|
||||
pour voir si ça ne crash pas.
|
||||
|
||||
Normal si le comportement attendu n'est pas correct (en l'absence de PATH et tout ça) mais ça ne devrait pas crasher pour autant.
|
||||
|
||||
*[\go to sommaire](#markdown-header-sommaire)*
|
||||
|
||||
12
echo
12
echo
@@ -1,12 +0,0 @@
|
||||
builds
|
||||
echo
|
||||
headers
|
||||
libft
|
||||
Makefile
|
||||
minishell
|
||||
minishell.en.subject.pdf
|
||||
README.md
|
||||
ressources
|
||||
srcs
|
||||
tests
|
||||
valgrind_readline.supp
|
||||
14
file.txt
14
file.txt
@@ -1,14 +0,0 @@
|
||||
builds
|
||||
echo
|
||||
file.txt
|
||||
headers
|
||||
libft
|
||||
Makefile
|
||||
minishell
|
||||
minishell.en.subject.pdf
|
||||
README.md
|
||||
ressources
|
||||
srcs
|
||||
tests
|
||||
test.txt
|
||||
valgrind_readline.supp
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/03 19:14:46 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/13 16:09:32 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/27 09:09:31 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
# include "libft.h"
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <errno.h>
|
||||
@@ -26,15 +27,19 @@
|
||||
# include <signal.h>
|
||||
# include <dirent.h>
|
||||
# include <termios.h>
|
||||
# include <curses.h> // sudo apt install libncurses-dev (OR libncurses5-dev)
|
||||
|
||||
// sudo apt install libncurses-dev (OR libncurses5-dev)
|
||||
# include <curses.h>
|
||||
# include <term.h>
|
||||
|
||||
# include <stdio.h>
|
||||
# include <readline/readline.h> // sudo apt install libreadline-dev
|
||||
// sudo apt install libreadline-dev
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
|
||||
# include "minishell_structs.h"
|
||||
# include <stdio.h>
|
||||
|
||||
# include "minishell_macro.h"
|
||||
# include "minishell_structs.h"
|
||||
# include "minishell_term_colors.h"
|
||||
# include "minishell_user_macro.h"
|
||||
# include "minishell_prototypes.h"
|
||||
@@ -52,8 +57,8 @@
|
||||
** <fcntl.h>: open()
|
||||
** <unistd.h>: read(), write(), close(), fork(), getcwd(), chdir(),
|
||||
** stat(), lstat(), fstat(), execve(), dup(), dup2(), pipe(),
|
||||
** isatty(), ttyname(), ttyslot(), ioctl(),
|
||||
** tcsetattr(), tcgetattr()
|
||||
** isatty(), ttyname(), ttyslot(), tcsetattr(), tcgetattr()
|
||||
** <sys/ioctl.h>: ioctl()
|
||||
** <stdlib.h>: malloc(), free(), exit(), getenv()
|
||||
** <string.h>: strerror(), define NULL, define size_t
|
||||
** <errno.h>: define errno
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 02:35:55 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/08 03:01:43 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/27 10:43:43 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -18,4 +18,37 @@
|
||||
# define PROMPT_CHEVRON "> "
|
||||
# define PROMPT_EURO "\001€\002 \001\b\002"
|
||||
|
||||
# define EXIT_CMD_NOT_FOUND 127
|
||||
# define EXIT_CMD_NOT_EXE 126
|
||||
# define EXIT_SIGNAL 128
|
||||
|
||||
// 1 and 125 inclusive
|
||||
# define EXIT_REDIRECTION 22
|
||||
# define EXIT_EXPANSION 33
|
||||
|
||||
enum e_lexer_return
|
||||
{
|
||||
CONTINUE_TOKEN = 1,
|
||||
DELIMITE_TOKEN
|
||||
};
|
||||
|
||||
enum e_token_id
|
||||
{
|
||||
T_LESS = '<',
|
||||
T_GREAT = '>',
|
||||
T_PIPE = '|',
|
||||
T_DLESS,
|
||||
T_DGREAT,
|
||||
T_WORD,
|
||||
T_REDIRECTION_WORD
|
||||
};
|
||||
// T_DLESS == '<<'
|
||||
// T_DGREAT == '>>'
|
||||
|
||||
enum e_quotes_state
|
||||
{
|
||||
IN_QUOTES = '\'',
|
||||
IN_DQUOTES = '\"'
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,33 +6,99 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/19 23:41:25 by hulamy ### ########.fr */
|
||||
/* Updated: 2021/12/22 19:28:07 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef MINISHELL_PROTOTYPES_H
|
||||
# define MINISHELL_PROTOTYPES_H
|
||||
|
||||
extern int g_switch_heredoc_sigint;
|
||||
extern char **environ;
|
||||
|
||||
// Init
|
||||
int init(t_all *c, char *envp[]);
|
||||
int init(t_all *c, char *argv[]);
|
||||
char *update_prompt(char *prompt_base);
|
||||
int retrieve_path(char **path_stock[]);
|
||||
void set_signals_behaviour(void);
|
||||
|
||||
// Shell modes
|
||||
void shell_loop(t_all *c);
|
||||
void shell_script(t_all *c, int script_fd);
|
||||
|
||||
// Lexer
|
||||
t_token *lexing(char *input);
|
||||
|
||||
// Parser
|
||||
t_cmd **parsing(t_token *token_list, int script_fd);
|
||||
int valid_syntax(t_token *token_list);
|
||||
int valid_token(t_token **token_list, enum e_token_id token_id);
|
||||
int valid_command_separator(const t_token *token_list);
|
||||
size_t count_pipes(t_token *token_list);
|
||||
t_cmd **pipeline_alloc(size_t cmd_nbr);
|
||||
int pipeline_fill_argv(t_token *token_list, t_cmd **pipeline);
|
||||
int expansions(t_token *token_list, t_cmd **pipeline);
|
||||
int token_expansions(t_token *t);
|
||||
int redirections(t_token *token_list, t_cmd **pipeline, int script_fd);
|
||||
|
||||
// Exec
|
||||
int exec_cmd_line(t_all *c);
|
||||
int pipeline(t_all *c);
|
||||
int cmd_find_access(t_cmd *cmd, char *path[]);
|
||||
int cmd_exec_in_subshell(t_cmd *cmd, t_all *c);
|
||||
void wait_subshell(pid_t last_cmd_pid);
|
||||
int simple_command_builtin(t_cmd *cmd, t_all *c);
|
||||
|
||||
// Builtins
|
||||
int builtin_env(int argc, char *argv[], t_all *c);
|
||||
int builtin_cd(int argc, char *argv[], t_all *c);
|
||||
int builtin_pwd(int argc, char *argv[], t_all *c);
|
||||
int builtin_export(int argc, char *argv[], t_all *c);
|
||||
int export_var(char *arg);
|
||||
int builtin_unset(int argc, char *argv[], t_all *c);
|
||||
int builtin_exit(int argc, char *argv[], t_all *c);
|
||||
int builtin_env(int argc, char *argv[], t_all *c);
|
||||
int builtin_echo(int argc, char *argv[], t_all *c);
|
||||
|
||||
// Free
|
||||
int free_exit(t_all *c, int exit_status);
|
||||
int exit_free(t_all *c, int exit_status);
|
||||
void free_pipeline(t_cmd **pipeline_ptr[]);
|
||||
void close_pipeline_fd(t_cmd *pipeline[]);
|
||||
void close_cmd_fd(t_cmd *cmd);
|
||||
void close_stdio(void);
|
||||
typedef void (*t_free_f)(void *); // generic
|
||||
|
||||
// Error wrappers
|
||||
int shell_error(char *s1, char *s2, char *s3, int ret_val);
|
||||
int shell_perror(char *s1, char *s2, char *s3, int ret_val);
|
||||
int ft_reti_perror_io(int ret, char *err_str, char *io_file);
|
||||
|
||||
// Generic
|
||||
char *ft_strjoinfree(char *s1, char *s2);
|
||||
char *ft_strjoinfree_s1(char *s1, const char *s2);
|
||||
char *ft_strjoinfree_s2(const char *s1, char *s2);
|
||||
void ft_lstprint(t_list *lst, int fd);
|
||||
int ft_isinset_str(char *str, char *set);
|
||||
size_t ft_2d_arrlen(void *ptr); // Replace ft_arrlen()
|
||||
char **ft_dup_2d_char_arr(char **ptr);
|
||||
void *ft_resize_2d_arr(void *ptr, size_t add_nbr);
|
||||
t_list *ft_lstbeforelast(t_list *lst);
|
||||
void *ft_lstnew_generic(size_t lst_size, size_t content_size);
|
||||
typedef void *(*t_dup_f)(void *);
|
||||
void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *));
|
||||
void ft_free_null(void *ptr);
|
||||
char *ft_getenv(char *env_var);
|
||||
size_t ft_getenv_position(char *env_var);
|
||||
int ft_is_posix_name(char *str);
|
||||
|
||||
// pipes hugo
|
||||
void pipes_hugo(char *input, t_all *c);
|
||||
// parser hugo
|
||||
void **cmd_path(char **argv, char **envp);
|
||||
int handle_fd(char **input, int i, int fdin, t_cmd *cmd);
|
||||
t_list *parser(char *input, char **envp);
|
||||
char **ft_split_quotes(char const *s, char c);
|
||||
char *ft_strdup_quotes(const char *s);
|
||||
|
||||
// Signals handler
|
||||
void sigint_handler_interactive(int signum);
|
||||
void sigint_handler_heredoc(int signum);
|
||||
|
||||
// last_exit_status
|
||||
int set_last_exit_status(int new_value);
|
||||
int get_last_exit_status(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,30 +6,43 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/20 09:11:41 by hulamy ### ########.fr */
|
||||
/* Updated: 2021/12/20 22:13:45 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef MINISHELL_STRUCTS_H
|
||||
# define MINISHELL_STRUCTS_H
|
||||
|
||||
typedef struct s_all
|
||||
struct s_all;
|
||||
|
||||
typedef struct s_token
|
||||
{
|
||||
char **envp;
|
||||
char *prompt_base;
|
||||
char *prompt;
|
||||
} t_all;
|
||||
char *content;
|
||||
struct s_token *next;
|
||||
enum e_token_id id;
|
||||
} t_token;
|
||||
|
||||
typedef int (*t_builtin_f)(int,char **,struct s_all *);
|
||||
|
||||
typedef struct s_cmd
|
||||
{
|
||||
char **argv;
|
||||
pid_t pid;
|
||||
void *builtin;
|
||||
int pipe_in;
|
||||
int pipe_out;
|
||||
int fd_redirect;
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
char **argv;
|
||||
char *path;
|
||||
t_builtin_f builtin_f;
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
pid_t pid;
|
||||
int error;
|
||||
} t_cmd;
|
||||
|
||||
typedef struct s_all
|
||||
{
|
||||
t_cmd **pipeline;
|
||||
char **path;
|
||||
char *prompt_base;
|
||||
char *prompt;
|
||||
t_token *token_list;
|
||||
int script_fd;
|
||||
} t_all;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/10 03:36:37 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/10 20:58:28 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/10/19 20:30:34 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
# include "minishell_macro.h"
|
||||
|
||||
# define U_PROMPT_END PROMPT_EURO
|
||||
# define U_PROMPT_END PROMPT_CHEVRON
|
||||
# define U_DEFAULT_USER "NoUser"
|
||||
# define U_DEFAULT_NAME "NoName"
|
||||
|
||||
|
||||
2
libft
2
libft
Submodule libft updated: 1401fddfcd...af88c1ce23
@@ -1 +0,0 @@
|
||||
https://raw.githubusercontent.com/kukinpower/minishell/master/images/3.png
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 345 KiB |
82
srcs/builtins/cd.c
Normal file
82
srcs/builtins/cd.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* cd.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/12/04 19:31:19 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 21:51:00 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
#define CMD "builtin_cd"
|
||||
|
||||
static int change_prompt(t_all *c);
|
||||
static int change_env_pwd(void);
|
||||
|
||||
int builtin_cd(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
char *dir;
|
||||
|
||||
if (argc > 2)
|
||||
return (shell_error("cd: ", "too many arguments", "", EXIT_FAILURE));
|
||||
else if (argc < 2 || ft_strncmp(argv[1], "~", 2) == 0)
|
||||
{
|
||||
dir = getenv("HOME");
|
||||
if (!dir)
|
||||
return (shell_error("cd: ", "HOME not set", "", EXIT_FAILURE));
|
||||
}
|
||||
else if (argc == 2)
|
||||
dir = argv[1];
|
||||
if (chdir(dir) == -1)
|
||||
return (shell_perror("cd: ", dir, ": ", EXIT_FAILURE));
|
||||
if (change_prompt(c) == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, CMD", change_prompt()"));
|
||||
if (change_env_pwd() == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, CMD", change_env_pwd()"));
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int change_prompt(t_all *c)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
tmp = update_prompt(c->prompt_base);
|
||||
if (!tmp)
|
||||
return (-1);
|
||||
free(c->prompt);
|
||||
c->prompt = tmp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int change_env_pwd(void)
|
||||
{
|
||||
char *tmp;
|
||||
int ret;
|
||||
|
||||
tmp = getenv("PWD");
|
||||
if (tmp)
|
||||
{
|
||||
tmp = ft_strjoin("OLDPWD=", tmp);
|
||||
if (!tmp)
|
||||
return (-1);
|
||||
ret = export_var(tmp);
|
||||
free(tmp);
|
||||
if (ret == -1)
|
||||
return (-1);
|
||||
}
|
||||
tmp = getcwd(NULL, 0);
|
||||
if (!tmp)
|
||||
return (-1);
|
||||
tmp = ft_strjoinfree_s2("PWD=", tmp);
|
||||
if (!tmp)
|
||||
return (-1);
|
||||
ret = export_var(tmp);
|
||||
free(tmp);
|
||||
if (ret == -1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
47
srcs/builtins/echo.c
Normal file
47
srcs/builtins/echo.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* echo.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/21 16:37:44 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/21 20:22:22 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
enum e_echo_options
|
||||
{
|
||||
BIT_N = 01,
|
||||
};
|
||||
|
||||
int builtin_echo(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
int i;
|
||||
int options;
|
||||
|
||||
(void)argc;
|
||||
(void)c;
|
||||
options = 0;
|
||||
i = 1;
|
||||
while (argv[i] && argv[i][0] == '-')
|
||||
{
|
||||
if (ft_isinset_str(&argv[i][1], "n"))
|
||||
options = options | BIT_N;
|
||||
else
|
||||
break ;
|
||||
i++;
|
||||
}
|
||||
while (argv[i])
|
||||
{
|
||||
ft_putstr_fd(argv[i], 1);
|
||||
i++;
|
||||
if (argv[i])
|
||||
write(1, " ", 1);
|
||||
}
|
||||
if ((options & BIT_N) == 0)
|
||||
write(1, "\n", 1);
|
||||
return (0);
|
||||
}
|
||||
@@ -6,16 +6,17 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/10 05:01:26 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/10 07:37:29 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/12/01 17:19:48 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int builtin_env(int argc, char *argv[], t_all *c) // WIP
|
||||
int builtin_env(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
ft_putendl_arr_fd(c->envp, 1);
|
||||
(void)c;
|
||||
ft_putendl_arr_fd(environ, 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/10 05:01:22 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/11 01:50:53 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/29 12:43:47 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int builtin_exit(int argc, char *argv[], t_all *c) // WIP
|
||||
int builtin_exit(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
unsigned char status;
|
||||
int i;
|
||||
|
||||
status = 0;
|
||||
status = get_last_exit_status();
|
||||
if (argc > 2)
|
||||
return (ft_reti_print(1, "exit: too many arguments\n", 2));
|
||||
if (argc == 2)
|
||||
@@ -36,7 +36,7 @@ int builtin_exit(int argc, char *argv[], t_all *c) // WIP
|
||||
return (ft_reti_print(2, " numeric argument required\n", 2));
|
||||
}
|
||||
}
|
||||
status = ft_atoi(argv[1]);
|
||||
status = ft_atoi(argv[1]);
|
||||
}
|
||||
return (free_exit(c, status));
|
||||
return (exit_free(c, status));
|
||||
}
|
||||
|
||||
96
srcs/builtins/export.c
Normal file
96
srcs/builtins/export.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* export.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/12/03 13:36:54 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 19:23:41 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int change_var_value(char *arg, char *var_name);
|
||||
|
||||
#define ERR_ID 1
|
||||
#define ERR_ID_STR ": not a valid identifier"
|
||||
#define CMD "builtin_export"
|
||||
|
||||
int builtin_export(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
int i;
|
||||
int exit_value;
|
||||
int ret;
|
||||
|
||||
(void)argc;
|
||||
exit_value = EXIT_SUCCESS;
|
||||
i = 1;
|
||||
while (argv[i])
|
||||
{
|
||||
ret = export_var(argv[i]);
|
||||
if (ret == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, CMD", export_var()"));
|
||||
else if (ret == ERR_ID)
|
||||
exit_value = EXIT_FAILURE;
|
||||
if (ft_strncmp(argv[i], "PATH=", 5) == 0)
|
||||
retrieve_path(&c->path);
|
||||
i++;
|
||||
}
|
||||
return (exit_value);
|
||||
}
|
||||
|
||||
// in complete shell, must mark arguments for export
|
||||
// (Not implemented in minishell)
|
||||
// arg == var_name[=value]
|
||||
// return "-1" on alloc error
|
||||
int export_var(char *arg)
|
||||
{
|
||||
char **var_split;
|
||||
int ret;
|
||||
|
||||
if (arg[0] != '_' && !ft_isalpha(arg[0]))
|
||||
return (shell_error("export: ", arg, ERR_ID_STR, ERR_ID));
|
||||
var_split = ft_split(arg, '=');
|
||||
if (!var_split)
|
||||
return (-1);
|
||||
if (!ft_is_posix_name(var_split[0]))
|
||||
{
|
||||
shell_error("export: ", var_split[0], ERR_ID_STR, 0);
|
||||
ft_free_2d_arr(var_split);
|
||||
return (ERR_ID);
|
||||
}
|
||||
ret = 0;
|
||||
if (ft_strchr(arg, '='))
|
||||
ret = change_var_value(arg, var_split[0]);
|
||||
ft_free_2d_arr(var_split);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int change_var_value(char *arg, char *var_name)
|
||||
{
|
||||
int env_position;
|
||||
char *tmp;
|
||||
|
||||
env_position = ft_getenv_position(var_name);
|
||||
if (environ[env_position] == NULL)
|
||||
{
|
||||
environ = ft_resize_2d_arr(environ, 1);
|
||||
if (!environ)
|
||||
return (ft_reti_perror(-1, CMD", ft_resize_2d_arr()"));
|
||||
}
|
||||
tmp = ft_strdup(arg);
|
||||
if (!tmp)
|
||||
return (ft_reti_perror(-1, CMD", ft_strdup()"));
|
||||
free(environ[env_position]);
|
||||
environ[env_position] = tmp;
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
environment variables must be POSIX NAME :
|
||||
3.235 Name
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
|
||||
#tag_03_235
|
||||
*/
|
||||
29
srcs/builtins/pwd.c
Normal file
29
srcs/builtins/pwd.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pwd.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/12/04 19:15:36 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/04 20:22:49 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int builtin_pwd(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
char *working_dir;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
(void)c;
|
||||
working_dir = getcwd(NULL, 0);
|
||||
if (!working_dir)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "builtin_pwd, getcwd()"));
|
||||
write(1, working_dir, ft_strlen(working_dir));
|
||||
write(1, "\n", 1);
|
||||
free(working_dir);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
61
srcs/builtins/unset.c
Normal file
61
srcs/builtins/unset.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* unset.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/12/05 17:05:05 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 19:23:50 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int unset_env_var(char *arg);
|
||||
|
||||
int builtin_unset(int argc, char *argv[], t_all *c)
|
||||
{
|
||||
int i;
|
||||
int exit_value;
|
||||
|
||||
(void)argc;
|
||||
(void)c;
|
||||
exit_value = EXIT_SUCCESS;
|
||||
i = 1;
|
||||
while (argv[i])
|
||||
{
|
||||
if (unset_env_var(argv[i]) == EXIT_FAILURE)
|
||||
exit_value = EXIT_FAILURE;
|
||||
if (ft_strncmp(argv[i], "PATH", 4 + 1) == 0)
|
||||
retrieve_path(&c->path);
|
||||
i++;
|
||||
}
|
||||
return (exit_value);
|
||||
}
|
||||
|
||||
static int unset_env_var(char *arg)
|
||||
{
|
||||
int env_position;
|
||||
|
||||
if (!ft_is_posix_name(arg))
|
||||
{
|
||||
shell_error("unset: ", arg, ": not a valid identifier", 0);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
env_position = ft_getenv_position(arg);
|
||||
free(environ[env_position]);
|
||||
while (environ[env_position])
|
||||
{
|
||||
environ[env_position] = environ[env_position + 1];
|
||||
env_position++;
|
||||
}
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
environment variables must be POSIX NAME :
|
||||
3.235 Name
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
|
||||
#tag_03_235
|
||||
*/
|
||||
29
srcs/exec/exec_cmd_line.c
Normal file
29
srcs/exec/exec_cmd_line.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* exec_cmd_line.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/01 16:07:48 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int exec_cmd_line(t_all *c)
|
||||
{
|
||||
if (!pipeline(c))
|
||||
{
|
||||
free_pipeline(&c->pipeline);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
2.9.1 Simple Commands - Command Search and Execution
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
#tag_18_09_01_01
|
||||
*/
|
||||
111
srcs/exec/find_access.c
Normal file
111
srcs/exec/find_access.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* find_access.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 15:03:31 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int search_cmd_path(char *cmd_name, char **cmd_path,
|
||||
char *path[]);
|
||||
static t_builtin_f search_builtin(char *cmd_name);
|
||||
static int handle_access_error(char *file_name);
|
||||
|
||||
/*
|
||||
* 2.8.2 Exit Status for Commands
|
||||
* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
* #tag_18_08_02
|
||||
*/
|
||||
|
||||
int cmd_find_access(t_cmd *cmd, char *path[])
|
||||
{
|
||||
if (ft_strchr(cmd->argv[0], '/'))
|
||||
{
|
||||
if (access(cmd->argv[0], X_OK) == -1)
|
||||
cmd->error = handle_access_error(cmd->argv[0]);
|
||||
else
|
||||
{
|
||||
cmd->path = ft_strdup(cmd->argv[0]);
|
||||
if (!cmd->path)
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->builtin_f = search_builtin(cmd->argv[0]);
|
||||
if (cmd->builtin_f)
|
||||
return (1);
|
||||
if (search_cmd_path(cmd->argv[0], &cmd->path, path) == -1)
|
||||
return (0);
|
||||
if (!cmd->path)
|
||||
{
|
||||
cmd->error = EXIT_CMD_NOT_FOUND;
|
||||
shell_error(cmd->argv[0], ": ", "command not found", 0);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int search_cmd_path(char *cmd_name, char **cmd_path, char *path[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!path)
|
||||
return (1);
|
||||
cmd_name = ft_strjoin("/", cmd_name);
|
||||
if (!cmd_name)
|
||||
return (ft_reti_perror(-1, "search_cmd_path()"));
|
||||
i = 0;
|
||||
while (path[i])
|
||||
{
|
||||
*cmd_path = ft_strjoin(path[i], cmd_name);
|
||||
if (!*cmd_path)
|
||||
return (ft_reti_perror(-1, "search_cmd_path()"));
|
||||
if (access(*cmd_path, X_OK) == 0)
|
||||
break ;
|
||||
else
|
||||
ft_free_null(cmd_path);
|
||||
i++;
|
||||
}
|
||||
free(cmd_name);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static t_builtin_f search_builtin(char *cmd_name)
|
||||
{
|
||||
if (ft_strncmp(cmd_name, "echo", 4 + 1) == 0)
|
||||
return (&builtin_echo);
|
||||
else if (ft_strncmp(cmd_name, "cd", 2 + 1) == 0)
|
||||
return (&builtin_cd);
|
||||
else if (ft_strncmp(cmd_name, "pwd", 3 + 1) == 0)
|
||||
return (&builtin_pwd);
|
||||
else if (ft_strncmp(cmd_name, "export", 6 + 1) == 0)
|
||||
return (&builtin_export);
|
||||
else if (ft_strncmp(cmd_name, "unset", 5 + 1) == 0)
|
||||
return (&builtin_unset);
|
||||
else if (ft_strncmp(cmd_name, "env", 3 + 1) == 0)
|
||||
return (&builtin_env);
|
||||
else if (ft_strncmp(cmd_name, "exit", 4 + 1) == 0)
|
||||
return (&builtin_exit);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int handle_access_error(char *file_name)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
tmp = errno;
|
||||
shell_perror(file_name, ": ", "", 0);
|
||||
errno = tmp;
|
||||
if (errno == EACCES)
|
||||
return (EXIT_CMD_NOT_EXE);
|
||||
else if (errno == ENOENT)
|
||||
return (EXIT_CMD_NOT_FOUND);
|
||||
return (1);
|
||||
}
|
||||
111
srcs/exec/pipeline.c
Normal file
111
srcs/exec/pipeline.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pipeline.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 18:08:16 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int open_pipes(t_cmd *pipeline[]);
|
||||
static int pipeline_find_access(t_cmd *pipeline[], char *path[]);
|
||||
static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c);
|
||||
|
||||
int pipeline(t_all *c)
|
||||
{
|
||||
t_cmd **pipeline;
|
||||
int ret;
|
||||
|
||||
pipeline = c->pipeline;
|
||||
if (!open_pipes(pipeline))
|
||||
return (0);
|
||||
if (!pipeline_find_access(pipeline, c->path))
|
||||
return (0);
|
||||
if (ft_2d_arrlen(pipeline) > 1)
|
||||
wait_subshell(pipeline_exec(pipeline, c));
|
||||
else
|
||||
{
|
||||
if (pipeline[0]->error)
|
||||
set_last_exit_status(pipeline[0]->error);
|
||||
else if (pipeline[0]->builtin_f)
|
||||
{
|
||||
ret = simple_command_builtin(pipeline[0], c);
|
||||
if (ret != EXIT_SUCCESS)
|
||||
set_last_exit_status(ret);
|
||||
}
|
||||
else
|
||||
wait_subshell(pipeline_exec(pipeline, c));
|
||||
}
|
||||
free_pipeline(&c->pipeline);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int open_pipes(t_cmd *pipeline[])
|
||||
{
|
||||
int i;
|
||||
int pipes[2];
|
||||
|
||||
i = 0;
|
||||
while (pipeline[i] && pipeline[i + 1])
|
||||
{
|
||||
if (pipe(pipes) == -1)
|
||||
return (ft_reti_perror(0, "pipe()"));
|
||||
if (pipeline[i]->fd_out == STDOUT_FILENO)
|
||||
pipeline[i]->fd_out = pipes[STDOUT_FILENO];
|
||||
else
|
||||
if (close(pipes[STDOUT_FILENO]) == -1)
|
||||
perror("close()");
|
||||
if (pipeline[i + 1]->fd_in == STDIN_FILENO)
|
||||
pipeline[i + 1]->fd_in = pipes[STDIN_FILENO];
|
||||
else
|
||||
if (close(pipes[STDIN_FILENO]) == -1)
|
||||
perror("close()");
|
||||
i++;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int pipeline_find_access(t_cmd *pipeline[], char *path[])
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (pipeline[i])
|
||||
{
|
||||
if (!pipeline[i]->error && pipeline[i]->argv[0])
|
||||
{
|
||||
if (!cmd_find_access(pipeline[i], path))
|
||||
return (0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
i = 0;
|
||||
while (pipeline[i])
|
||||
{
|
||||
if (!pipeline[i]->error && pipeline[i]->argv[0])
|
||||
{
|
||||
ret = cmd_exec_in_subshell(pipeline[i], c);
|
||||
if (ret != EXIT_SUCCESS)
|
||||
exit_free(c, ret);
|
||||
}
|
||||
close_cmd_fd(pipeline[i]);
|
||||
i++;
|
||||
}
|
||||
i -= 1;
|
||||
if (pipeline[i]->error)
|
||||
set_last_exit_status(pipeline[i]->error);
|
||||
return (pipeline[i]->pid);
|
||||
}
|
||||
63
srcs/exec/simple_cmd_builtin.c
Normal file
63
srcs/exec/simple_cmd_builtin.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* simple_cmd_builtin.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/01 16:49:37 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int restore_stdio(int stdin_dup, int stdout_dup);
|
||||
|
||||
int simple_command_builtin(t_cmd *cmd, t_all *c)
|
||||
{
|
||||
int stdin_dup;
|
||||
int stdout_dup;
|
||||
|
||||
stdin_dup = 0;
|
||||
stdout_dup = 0;
|
||||
if (cmd->fd_in != STDIN_FILENO)
|
||||
{
|
||||
stdin_dup = dup(STDIN_FILENO);
|
||||
if (stdin_dup == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "dup()"));
|
||||
if (dup2(cmd->fd_in, STDIN_FILENO) == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
|
||||
}
|
||||
if (cmd->fd_out != STDOUT_FILENO)
|
||||
{
|
||||
stdout_dup = dup(STDOUT_FILENO);
|
||||
if (stdout_dup == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "dup()"));
|
||||
if (dup2(cmd->fd_out, STDOUT_FILENO) == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
|
||||
}
|
||||
set_last_exit_status(cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c));
|
||||
if (!restore_stdio(stdin_dup, stdout_dup))
|
||||
return (EXIT_FAILURE);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int restore_stdio(int stdin_dup, int stdout_dup)
|
||||
{
|
||||
if (stdin_dup)
|
||||
{
|
||||
if (dup2(stdin_dup, STDIN_FILENO) == -1)
|
||||
return (ft_reti_perror(0, "dup2()"));
|
||||
if (close(stdin_dup) == -1)
|
||||
return (ft_reti_perror(0, "close()"));
|
||||
}
|
||||
if (stdout_dup)
|
||||
{
|
||||
if (dup2(stdout_dup, STDOUT_FILENO) == -1)
|
||||
return (ft_reti_perror(0, "dup2()"));
|
||||
if (close(stdout_dup) == -1)
|
||||
return (ft_reti_perror(0, "close()"));
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
55
srcs/exec/subshell_exec.c
Normal file
55
srcs/exec/subshell_exec.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* subshell_exec.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 22:12:16 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static void exec_builtin(t_cmd *cmd, t_all *c);
|
||||
|
||||
int cmd_exec_in_subshell(t_cmd *cmd, t_all *c)
|
||||
{
|
||||
struct sigaction signal_behaviour;
|
||||
|
||||
cmd->pid = fork();
|
||||
if (cmd->pid == -1)
|
||||
perror("fork()");
|
||||
if (cmd->pid == 0)
|
||||
{
|
||||
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
|
||||
signal_behaviour.sa_handler = SIG_DFL;
|
||||
sigaction(SIGINT, &signal_behaviour, NULL);
|
||||
sigaction(SIGQUIT, &signal_behaviour, NULL);
|
||||
if (cmd->fd_in != STDIN_FILENO)
|
||||
if (dup2(cmd->fd_in, STDIN_FILENO) == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
|
||||
if (cmd->fd_out != STDOUT_FILENO)
|
||||
if (dup2(cmd->fd_out, STDOUT_FILENO) == -1)
|
||||
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
|
||||
close_pipeline_fd(c->pipeline);
|
||||
if (cmd->builtin_f)
|
||||
exec_builtin(cmd, c);
|
||||
else if (execve(cmd->path, cmd->argv, environ) == -1)
|
||||
return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0]));
|
||||
}
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void exec_builtin(t_cmd *cmd, t_all *c)
|
||||
{
|
||||
struct sigaction signal_behaviour;
|
||||
int ret;
|
||||
|
||||
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
|
||||
signal_behaviour.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &signal_behaviour, NULL);
|
||||
ret = cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c);
|
||||
exit_free(c, ret);
|
||||
}
|
||||
65
srcs/exec/subshell_wait.c
Normal file
65
srcs/exec/subshell_wait.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* subshell_wait.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 15:38:01 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static void handle_signal_status(int wstatus);
|
||||
static int handle_wait_error(void);
|
||||
|
||||
void wait_subshell(pid_t last_cmd_pid)
|
||||
{
|
||||
int wstatus;
|
||||
int ret;
|
||||
|
||||
wstatus = 0;
|
||||
if (last_cmd_pid > 0)
|
||||
{
|
||||
if (waitpid(last_cmd_pid, &wstatus, 0) == -1)
|
||||
perror("waitpid()");
|
||||
if (WIFEXITED(wstatus))
|
||||
set_last_exit_status(WEXITSTATUS(wstatus));
|
||||
if (WIFSIGNALED(wstatus))
|
||||
handle_signal_status(wstatus);
|
||||
}
|
||||
ret = 0;
|
||||
while (ret != -1)
|
||||
{
|
||||
ret = wait(&wstatus);
|
||||
if (ret == -1)
|
||||
ret = handle_wait_error();
|
||||
}
|
||||
if (get_last_exit_status() == EXIT_SIGNAL + SIGSEGV)
|
||||
ft_putstr_fd("Segmentation fault (core dumped)\n", STDERR_FILENO);
|
||||
}
|
||||
|
||||
static void handle_signal_status(int wstatus)
|
||||
{
|
||||
int signum;
|
||||
|
||||
signum = WTERMSIG(wstatus);
|
||||
set_last_exit_status(EXIT_SIGNAL + signum);
|
||||
if (signum == SIGINT)
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
if (signum == SIGQUIT)
|
||||
ft_putstr_fd("Quit (core dumped)\n", STDERR_FILENO);
|
||||
}
|
||||
|
||||
static int handle_wait_error(void)
|
||||
{
|
||||
if (errno == ECHILD)
|
||||
return (-1);
|
||||
else if (errno == EINTR)
|
||||
return (0);
|
||||
else
|
||||
perror("wait()");
|
||||
return (-1);
|
||||
}
|
||||
67
srcs/generic/ft_2d_arr_func.c
Normal file
67
srcs/generic/ft_2d_arr_func.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_2d_arr_func.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/16 03:43:33 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
// Replace ft_arrlen()
|
||||
size_t ft_2d_arrlen(void *ptr)
|
||||
{
|
||||
size_t len;
|
||||
char **arr;
|
||||
|
||||
arr = (char **)ptr;
|
||||
len = 0;
|
||||
while (arr[len] != NULL)
|
||||
len++;
|
||||
return (len);
|
||||
}
|
||||
|
||||
void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *))
|
||||
{
|
||||
unsigned int i;
|
||||
char **arr;
|
||||
char **new_arr;
|
||||
|
||||
new_arr = ft_calloc(ft_2d_arrlen(ptr) + 1, sizeof (void *));
|
||||
if (!new_arr)
|
||||
return (NULL);
|
||||
arr = (char **)ptr;
|
||||
i = 0;
|
||||
while (arr[i])
|
||||
{
|
||||
new_arr[i] = dup_func(arr[i]);
|
||||
if (!new_arr[i])
|
||||
return (ft_retp_free(NULL, new_arr, ft_free_2d_arr));
|
||||
i++;
|
||||
}
|
||||
return (new_arr);
|
||||
}
|
||||
|
||||
void *ft_resize_2d_arr(void *ptr, size_t add_nbr)
|
||||
{
|
||||
unsigned int i;
|
||||
char **arr;
|
||||
char **new_arr;
|
||||
|
||||
new_arr = ft_calloc(ft_2d_arrlen(ptr) + add_nbr + 1, sizeof (void *));
|
||||
if (!new_arr)
|
||||
return (NULL);
|
||||
arr = (char **)ptr;
|
||||
i = 0;
|
||||
while (arr[i])
|
||||
{
|
||||
new_arr[i] = arr[i];
|
||||
i++;
|
||||
}
|
||||
free(arr);
|
||||
return (new_arr);
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* free.c :+: :+: :+: */
|
||||
/* ft_free_null.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/10 23:59:25 by lperrey ### ########.fr */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/16 03:59:21 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int free_exit(t_all *c, int exit_status)
|
||||
void ft_free_null(void *ptr)
|
||||
{
|
||||
free(c->prompt_base);
|
||||
free(c->prompt);
|
||||
exit(exit_status);
|
||||
free(*(char **)ptr);
|
||||
*(char **)ptr = NULL;
|
||||
}
|
||||
70
srcs/generic/ft_getenv.c
Normal file
70
srcs/generic/ft_getenv.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_getenv.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 18:07:16 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
/*
|
||||
** Search for an environement variable,
|
||||
** and return a pointer to the first character after "env_var=" .
|
||||
** Return NULL if env_var not found.
|
||||
*/
|
||||
char *ft_getenv(char *env_var)
|
||||
{
|
||||
int i;
|
||||
char *tmp;
|
||||
size_t env_var_len;
|
||||
|
||||
env_var_len = ft_strlen(env_var);
|
||||
i = 0;
|
||||
tmp = NULL;
|
||||
while (!tmp && environ[i])
|
||||
{
|
||||
if (environ[i][env_var_len] == '=')
|
||||
{
|
||||
if (ft_strncmp(environ[i], env_var, env_var_len) == 0)
|
||||
tmp = &environ[i][env_var_len + 1];
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** Like ft_getenv(), but return position of env_var instead of value.
|
||||
** If env_var not found, return last position of **environ (== NULL)
|
||||
*/
|
||||
size_t ft_getenv_position(char *env_var)
|
||||
{
|
||||
int i;
|
||||
int found;
|
||||
size_t env_var_len;
|
||||
|
||||
env_var_len = ft_strlen(env_var);
|
||||
i = 0;
|
||||
found = 0;
|
||||
while (!found && environ[i])
|
||||
{
|
||||
if (ft_strncmp(environ[i], env_var, env_var_len) == 0)
|
||||
{
|
||||
if (environ[i][env_var_len] == '=')
|
||||
found = 1;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
31
srcs/generic/ft_is_posix_name.c
Normal file
31
srcs/generic/ft_is_posix_name.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_is_posix_name.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/18 13:31:11 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int ft_is_posix_name(char *str)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!str)
|
||||
return (0);
|
||||
if (str[0] != '_' && !ft_isalpha(str[0]))
|
||||
return (0);
|
||||
i = 1;
|
||||
while (str[i])
|
||||
{
|
||||
if (str[i] != '_' && !ft_isalnum(str[i]))
|
||||
return (0);
|
||||
i++;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
37
srcs/generic/ft_isinset_str.c
Normal file
37
srcs/generic/ft_isinset_str.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_isinset_str.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/16 03:45:50 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int ft_isinset_str(char *str, char *set)
|
||||
{
|
||||
size_t i;
|
||||
size_t i_set;
|
||||
int valid;
|
||||
|
||||
i = 0;
|
||||
while (str[i])
|
||||
{
|
||||
valid = 0;
|
||||
i_set = 0;
|
||||
while (set[i_set] && !valid)
|
||||
{
|
||||
if (str[i] == set[i_set])
|
||||
valid = 1;
|
||||
i_set++;
|
||||
}
|
||||
if (!valid)
|
||||
return (0);
|
||||
i++;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
56
srcs/generic/ft_lst_func.c
Normal file
56
srcs/generic/ft_lst_func.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_lst_func.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/16 03:45:39 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void ft_lstprint(t_list *lst, int fd)
|
||||
{
|
||||
while (lst)
|
||||
{
|
||||
ft_putendl_fd(lst->content, fd);
|
||||
lst = lst->next;
|
||||
}
|
||||
}
|
||||
|
||||
t_list *ft_lstbeforelast(t_list *lst)
|
||||
{
|
||||
if (!lst || !lst->next)
|
||||
return (NULL);
|
||||
while (lst->next->next)
|
||||
lst = lst->next;
|
||||
return (lst);
|
||||
}
|
||||
|
||||
/* if "content_size == 0", return lst with "lst->content == NULL" */
|
||||
void *ft_lstnew_generic(size_t lst_size, size_t content_size)
|
||||
{
|
||||
t_list *elem;
|
||||
void *content;
|
||||
|
||||
if (content_size == 0)
|
||||
content = NULL;
|
||||
else
|
||||
{
|
||||
content = ft_calloc(content_size, 1);
|
||||
if (!content)
|
||||
return (NULL);
|
||||
}
|
||||
elem = ft_calloc(1, lst_size);
|
||||
if (!elem)
|
||||
{
|
||||
free(content);
|
||||
return (NULL);
|
||||
}
|
||||
elem->content = content;
|
||||
elem->next = NULL;
|
||||
return (elem);
|
||||
}
|
||||
179
srcs/generic/ft_split_quotes.c
Normal file
179
srcs/generic/ft_split_quotes.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_split_quotes.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/13 07:08:40 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 16:45:10 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static size_t count_word(char const *s, char c);
|
||||
static char **alloc_words(char const *s, char c, char **str_arr,
|
||||
size_t words_count);
|
||||
static void fill_arr(char const *s, char c, char **str_arr);
|
||||
static int quote_state_change(int *quote_state, const char *s);
|
||||
|
||||
char **ft_split_quotes(char const *s, char c)
|
||||
{
|
||||
char **str_arr;
|
||||
size_t words_count;
|
||||
|
||||
if (s == NULL)
|
||||
return (NULL);
|
||||
words_count = count_word(s, c);
|
||||
str_arr = ft_calloc(words_count + 1, sizeof(char *));
|
||||
if (!str_arr)
|
||||
return (NULL);
|
||||
if (!(alloc_words(s, c, str_arr, words_count)))
|
||||
{
|
||||
ft_free_2d_arr(str_arr);
|
||||
return (NULL);
|
||||
}
|
||||
fill_arr(s, c, str_arr);
|
||||
return (str_arr);
|
||||
}
|
||||
|
||||
static size_t count_word(char const *s, char c)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t count;
|
||||
int quote_state;
|
||||
|
||||
i = 0;
|
||||
count = 0;
|
||||
quote_state = 0;
|
||||
while (s[i])
|
||||
{
|
||||
while (s[i] == c)
|
||||
i++;
|
||||
if (s[i])
|
||||
count++;
|
||||
while (s[i] && (s[i] != c || quote_state))
|
||||
{
|
||||
while (quote_state_change("e_state, &s[i]))
|
||||
i++;
|
||||
if (s[i] && (s[i] != c || quote_state))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
|
||||
static char **alloc_words(char const *s, char c, char **str_arr,
|
||||
size_t words_count)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t len;
|
||||
unsigned int arr_i;
|
||||
int quote_state;
|
||||
|
||||
i = 0;
|
||||
arr_i = 0;
|
||||
quote_state = 0;
|
||||
while (arr_i < words_count)
|
||||
{
|
||||
len = 0;
|
||||
while (s[i] == c)
|
||||
i++;
|
||||
while (s[i + len]
|
||||
&& (quote_state_change("e_state, &s[i + len])
|
||||
|| (s[i + len] != c || quote_state)))
|
||||
len++;
|
||||
i = i + len;
|
||||
str_arr[arr_i] = ft_calloc(len + 1, 1);
|
||||
if (!str_arr[arr_i])
|
||||
return (NULL);
|
||||
arr_i++;
|
||||
}
|
||||
return (str_arr);
|
||||
}
|
||||
|
||||
// Plus clair, plus de 25 lignes :(
|
||||
/* static char **alloc_words(char const *s, char c, char **str_arr,
|
||||
size_t words_count)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t len;
|
||||
unsigned int arr_i;
|
||||
int quote_state;
|
||||
|
||||
i = 0;
|
||||
arr_i = 0;
|
||||
quote_state = 0;
|
||||
while (arr_i < words_count)
|
||||
{
|
||||
len = 0;
|
||||
while (s[i] == c)
|
||||
i++;
|
||||
while (s[i + len] && (s[i + len] != c || quote_state))
|
||||
{
|
||||
while (quote_state_change("e_state, &s[i + len]))
|
||||
len++;
|
||||
if (s[i + len] != c || quote_state)
|
||||
len++;
|
||||
}
|
||||
i = i + len;
|
||||
str_arr[arr_i] = ft_calloc(len + 1, 1);
|
||||
if (!str_arr[arr_i])
|
||||
return (NULL);
|
||||
arr_i++;
|
||||
}
|
||||
return (str_arr);
|
||||
} */
|
||||
|
||||
static void fill_arr(char const *s, char c, char **str_arr)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int arr_i;
|
||||
unsigned int char_i;
|
||||
int quote_state;
|
||||
|
||||
i = 0;
|
||||
arr_i = 0;
|
||||
quote_state = 0;
|
||||
while (str_arr[arr_i])
|
||||
{
|
||||
while (s[i] == c)
|
||||
i++;
|
||||
char_i = 0;
|
||||
while (s[i] && (s[i] != c || quote_state))
|
||||
{
|
||||
while (quote_state_change("e_state, &s[i]))
|
||||
str_arr[arr_i][char_i++] = s[i++];
|
||||
if (s[i] && (s[i] != c || quote_state))
|
||||
str_arr[arr_i][char_i++] = s[i++];
|
||||
}
|
||||
str_arr[arr_i][char_i] = '\0';
|
||||
arr_i++;
|
||||
}
|
||||
}
|
||||
|
||||
static int quote_state_change(int *quote_state, const char *s)
|
||||
{
|
||||
if (s[0] == '\'' && *quote_state != IN_DQUOTES)
|
||||
{
|
||||
if (*quote_state == IN_QUOTES)
|
||||
*quote_state = 0;
|
||||
else if (ft_strchr(&s[1], '\''))
|
||||
*quote_state = IN_QUOTES;
|
||||
else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
else if (s[0] == '\"' && *quote_state != IN_QUOTES)
|
||||
{
|
||||
if (*quote_state == IN_DQUOTES)
|
||||
*quote_state = 0;
|
||||
else if (ft_strchr(&s[1], '\"'))
|
||||
*quote_state = IN_DQUOTES;
|
||||
else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
64
srcs/generic/ft_strdup_quotes.c
Normal file
64
srcs/generic/ft_strdup_quotes.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ft_strdup_quotes.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/13 04:35:06 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 16:29:27 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int quote_state_change(int *quote_state, const char *s);
|
||||
|
||||
/* Duplicate a string minus the quoting characters ['] and ["]*/
|
||||
char *ft_strdup_quotes(const char *s)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i_dup;
|
||||
char *dup;
|
||||
int quote_state;
|
||||
|
||||
dup = ft_calloc(ft_strlen(s) + 1, 1);
|
||||
if (!dup)
|
||||
return (NULL);
|
||||
i = 0;
|
||||
i_dup = 0;
|
||||
quote_state = 0;
|
||||
while (s[i])
|
||||
{
|
||||
while (quote_state_change("e_state, &s[i]))
|
||||
i++;
|
||||
if (s[i])
|
||||
dup[i_dup++] = s[i++];
|
||||
}
|
||||
return (dup);
|
||||
}
|
||||
|
||||
static int quote_state_change(int *quote_state, const char *s)
|
||||
{
|
||||
if (s[0] == '\'' && *quote_state != IN_DQUOTES)
|
||||
{
|
||||
if (*quote_state == IN_QUOTES)
|
||||
*quote_state = 0;
|
||||
else if (ft_strchr(&s[1], '\''))
|
||||
*quote_state = IN_QUOTES;
|
||||
else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
else if (s[0] == '\"' && *quote_state != IN_QUOTES)
|
||||
{
|
||||
if (*quote_state == IN_DQUOTES)
|
||||
*quote_state = 0;
|
||||
else if (ft_strchr(&s[1], '\"'))
|
||||
*quote_state = IN_DQUOTES;
|
||||
else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* generic.c :+: :+: :+: */
|
||||
/* ft_strjoinfree.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/08 09:28:49 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/12/16 03:39:09 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
35
srcs/init/init.c
Normal file
35
srcs/init/init.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* init.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 19:24:04 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void init_readline(void);
|
||||
int init_shlvl(void);
|
||||
void open_script_file(t_all *c, char *argv[]);
|
||||
int init_prompt(t_all *c, int script_fd);
|
||||
|
||||
int init(t_all *c, char *argv[])
|
||||
{
|
||||
ft_bzero(c, sizeof (*c));
|
||||
set_signals_behaviour();
|
||||
init_readline();
|
||||
environ = ft_dup_2d_arr(environ, (t_dup_f)ft_strdup);
|
||||
if (!environ)
|
||||
return (ft_reti_perror(0, "ft_dup_2d_arr(environ)"));
|
||||
retrieve_path(&c->path);
|
||||
if (!init_shlvl())
|
||||
return (ft_reti_perror(0, "init_shlvl()"));
|
||||
open_script_file(c, argv);
|
||||
if (!init_prompt(c, c->script_fd))
|
||||
return (ft_reti_perror(0, "init_prompt()"));
|
||||
return (1);
|
||||
}
|
||||
@@ -1,30 +1,30 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* init.c :+: :+: :+: */
|
||||
/* init_prompt.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/10 21:56:33 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/12/20 22:25:46 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static char *init_prompt_base(void);
|
||||
static char *init_prompt(char *prompt_base);
|
||||
|
||||
int init(t_all *c, char *envp[])
|
||||
int init_prompt(t_all *c, int script_fd)
|
||||
{
|
||||
ft_bzero(c, sizeof *c);
|
||||
c->envp = envp;
|
||||
c->prompt_base = init_prompt_base();
|
||||
if (!c->prompt_base)
|
||||
return (ft_reti_perror(0, "init_prompt_base() fail"));
|
||||
c->prompt = init_prompt(c->prompt_base);
|
||||
if (!c->prompt)
|
||||
return (ft_reti_perror(0, "init_prompt() fail"));
|
||||
if (!script_fd && isatty(STDIN_FILENO))
|
||||
{
|
||||
c->prompt_base = init_prompt_base();
|
||||
if (!c->prompt_base)
|
||||
return (0);
|
||||
c->prompt = update_prompt(c->prompt_base);
|
||||
if (!c->prompt)
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -39,20 +39,32 @@ static char *init_prompt_base(void)
|
||||
if (!tmp)
|
||||
tmp = U_DEFAULT_USER;
|
||||
prompt_base = ft_strjoin(TERM_LIGHT_GREEN, tmp);
|
||||
if (!prompt_base)
|
||||
return (NULL);
|
||||
prompt_base = ft_strjoinfree_s1(prompt_base, "@");
|
||||
if (!prompt_base)
|
||||
return (NULL);
|
||||
tmp = getenv("NAME");
|
||||
if (!tmp)
|
||||
tmp = U_DEFAULT_NAME;
|
||||
prompt_base = ft_strjoinfree_s1(prompt_base, tmp);
|
||||
if (!prompt_base)
|
||||
return (NULL);
|
||||
prompt_base = ft_strjoinfree_s1(prompt_base, TERM_RESET":"TERM_LIGHT_BLUE);
|
||||
if (!prompt_base)
|
||||
return (NULL);
|
||||
return (prompt_base);
|
||||
}
|
||||
|
||||
static char *init_prompt(char *prompt_base)
|
||||
char *update_prompt(char *prompt_base)
|
||||
{
|
||||
char *prompt;
|
||||
|
||||
prompt = ft_strjoinfree_s2(prompt_base, getcwd(NULL, 0));
|
||||
if (!prompt)
|
||||
return (NULL);
|
||||
prompt = ft_strjoinfree_s1(prompt, TERM_RESET U_PROMPT_END);
|
||||
if (!prompt)
|
||||
return (NULL);
|
||||
return (prompt);
|
||||
}
|
||||
33
srcs/init/init_readline.c
Normal file
33
srcs/init/init_readline.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* init_readline.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/18 04:31:59 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int init_readline_hook(void);
|
||||
|
||||
void init_readline(void)
|
||||
{
|
||||
rl_outstream = stderr;
|
||||
rl_startup_hook = init_readline_hook;
|
||||
readline(NULL);
|
||||
rl_startup_hook = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** set rl_startup_hook with this, for init COLUMNS and LINES variables
|
||||
** and prevent leak/double_free with **environ
|
||||
*/
|
||||
static int init_readline_hook(void)
|
||||
{
|
||||
rl_done = 1;
|
||||
return (0);
|
||||
}
|
||||
37
srcs/init/init_shlvl.c
Normal file
37
srcs/init/init_shlvl.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* init_shlvl.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/18 04:35:33 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int init_shlvl(void)
|
||||
{
|
||||
char *tmp;
|
||||
int ret;
|
||||
|
||||
tmp = getenv("SHLVL");
|
||||
if (tmp && ft_isdigit_str(tmp))
|
||||
{
|
||||
tmp = ft_itoa(ft_atoi(tmp) + 1);
|
||||
if (!tmp)
|
||||
return (0);
|
||||
tmp = ft_strjoinfree_s2("SHLVL=", tmp);
|
||||
if (!tmp)
|
||||
return (0);
|
||||
ret = export_var(tmp);
|
||||
free(tmp);
|
||||
}
|
||||
else
|
||||
ret = export_var("SHLVL=1");
|
||||
if (ret == -1)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
26
srcs/init/open_script_file.c
Normal file
26
srcs/init/open_script_file.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* open_script_file.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/12/20 22:22:29 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 22:27:14 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void open_script_file(t_all *c, char *argv[])
|
||||
{
|
||||
if (argv[1])
|
||||
{
|
||||
c->script_fd = open(argv[1], O_RDONLY);
|
||||
if (c->script_fd == -1)
|
||||
{
|
||||
shell_perror(argv[1], ": ", "", 0);
|
||||
exit_free(c, EXIT_CMD_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
srcs/lexing/check_operators.c
Normal file
65
srcs/lexing/check_operators.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* check_operators.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/19 08:38:55 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/30 22:37:08 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int check_redirection(t_token *t, char *input, int *i, int *t_i);
|
||||
static int check_pipe(t_token *t, char *input, int *i, int *t_i);
|
||||
|
||||
int check_operators(t_token *t, char *input, int *i, int *t_i)
|
||||
{
|
||||
if (*t_i != 0 && (input[*i] == '|' || input[*i] == '<' || input[*i] == '>'))
|
||||
return (DELIMITE_TOKEN);
|
||||
else if (check_pipe(t, input, i, t_i))
|
||||
return (DELIMITE_TOKEN);
|
||||
else if (check_redirection(t, input, i, t_i))
|
||||
return (DELIMITE_TOKEN);
|
||||
return (CONTINUE_TOKEN);
|
||||
}
|
||||
|
||||
static int check_pipe(t_token *t, char *input, int *i, int *t_i)
|
||||
{
|
||||
if (input[*i] == '|')
|
||||
{
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
t->id = T_PIPE;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int check_redirection(t_token *t, char *input, int *i, int *t_i)
|
||||
{
|
||||
if (input[*i] == '<')
|
||||
{
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
t->id = T_LESS;
|
||||
if (input[*i] == '<')
|
||||
{
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
t->id = T_DLESS;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
else if (input[*i] == '>')
|
||||
{
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
t->id = T_GREAT;
|
||||
if (input[*i] == '>')
|
||||
{
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
t->id = T_DGREAT;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
63
srcs/lexing/fill_token.c
Normal file
63
srcs/lexing/fill_token.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* fill_token.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/19 08:38:55 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/01 16:00:48 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int check_operators(t_token *t, char *input, int *i, int *t_i);
|
||||
|
||||
static int quoting(int *quotes_state, char *input, int *i);
|
||||
|
||||
int fill_token(t_token *t, char *input, int *i, int *t_i)
|
||||
{
|
||||
static int quotes_state = 0;
|
||||
|
||||
if (!quotes_state)
|
||||
{
|
||||
if (check_operators(t, input, i, t_i) == DELIMITE_TOKEN)
|
||||
return (DELIMITE_TOKEN);
|
||||
}
|
||||
if (quoting("es_state, input, i))
|
||||
{
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
return (CONTINUE_TOKEN);
|
||||
}
|
||||
if (!quotes_state && (input[*i] == ' ' || input[*i] == '\t'))
|
||||
{
|
||||
while (input[*i] == ' ' || input[*i] == '\t')
|
||||
(*i)++;
|
||||
return (DELIMITE_TOKEN);
|
||||
}
|
||||
else
|
||||
t->content[(*t_i)++] = input[(*i)++];
|
||||
return (CONTINUE_TOKEN);
|
||||
}
|
||||
|
||||
static int quoting(int *quotes_state, char *input, int *i)
|
||||
{
|
||||
if (input[*i] == '\'' && *quotes_state != IN_DQUOTES)
|
||||
{
|
||||
if (*quotes_state == IN_QUOTES)
|
||||
*quotes_state = 0;
|
||||
else if (ft_strchr(&input[*i + 1], '\''))
|
||||
*quotes_state = IN_QUOTES;
|
||||
return (CONTINUE_TOKEN);
|
||||
}
|
||||
else if (input[*i] == '\"' && *quotes_state != IN_QUOTES)
|
||||
{
|
||||
if (*quotes_state == IN_DQUOTES)
|
||||
*quotes_state = 0;
|
||||
else if (ft_strchr(&input[*i + 1], '\"'))
|
||||
*quotes_state = IN_DQUOTES;
|
||||
return (CONTINUE_TOKEN);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
69
srcs/lexing/lexing.c
Normal file
69
srcs/lexing/lexing.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* lexing.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/19 08:38:55 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/05 17:11:31 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int fill_token(t_token *t, char *input, int *i, int *t_i);
|
||||
|
||||
static int tokenize_input(t_token *t, char *input, size_t input_len);
|
||||
|
||||
t_token *lexing(char *input)
|
||||
{
|
||||
t_token *t_head;
|
||||
t_token *t_tmp;
|
||||
size_t input_len;
|
||||
|
||||
input_len = ft_strlen(input);
|
||||
t_head = ft_lstnew_generic(sizeof(t_token), input_len + 1);
|
||||
if (!t_head)
|
||||
return (ft_retp_perror(NULL, "ft_lstnew_generic() error"));
|
||||
if (!tokenize_input(t_head, input, input_len))
|
||||
return (ft_lstclear((t_list **)&t_head, free));
|
||||
t_tmp = (t_token *)ft_lstbeforelast((t_list *)t_head);
|
||||
if (t_tmp && t_tmp->next && !t_tmp->next->id)
|
||||
{
|
||||
ft_lstdelone((t_list *)t_tmp->next, free);
|
||||
t_tmp->next = NULL;
|
||||
}
|
||||
return (t_head);
|
||||
}
|
||||
|
||||
static int tokenize_input(t_token *t, char *input, size_t input_len)
|
||||
{
|
||||
int i;
|
||||
int t_i;
|
||||
|
||||
i = 0;
|
||||
t_i = 0;
|
||||
while (input[i])
|
||||
{
|
||||
if (fill_token(t, input, &i, &t_i) == DELIMITE_TOKEN && input[i] && t_i)
|
||||
{
|
||||
if (!t->id)
|
||||
t->id = T_WORD;
|
||||
t->next = ft_lstnew_generic(sizeof(t_token), input_len + 1 - i);
|
||||
if (!t->next)
|
||||
return (ft_reti_perror(0, "ft_lstnew_generic() error"));
|
||||
t = t->next;
|
||||
t_i = 0;
|
||||
}
|
||||
}
|
||||
if (!t->id && t_i)
|
||||
t->id = T_WORD;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
2.3 Token Recognition
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
#tag_18_03
|
||||
*/
|
||||
124
srcs/main.c
124
srcs/main.c
@@ -1,113 +1,31 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* main.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 22:26:14 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void close_fd(t_cmd *cmd, pid_t pid)
|
||||
{
|
||||
if (cmd->fd_in != 0)
|
||||
close(cmd->fd_in);
|
||||
if (pid == 0)
|
||||
{
|
||||
if (cmd->pipe_out != 1)
|
||||
{
|
||||
close(cmd->pipe_in);
|
||||
close(cmd->pipe_out);
|
||||
}
|
||||
if (cmd->fd_out != 1)
|
||||
close(cmd->fd_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmd->fd_out != 1 && cmd->fd_redirect == 1)
|
||||
close(cmd->fd_out);
|
||||
}
|
||||
}
|
||||
int g_switch_heredoc_sigint;
|
||||
|
||||
void exec_cmd(char **envp, t_list *cmd_list)
|
||||
{
|
||||
t_cmd *cmd;
|
||||
pid_t pid;
|
||||
pid_t wpid;
|
||||
int status;
|
||||
|
||||
while(cmd_list)
|
||||
{
|
||||
cmd = cmd_list->content;
|
||||
pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
if (cmd->fd_in != 0)
|
||||
dup2(cmd->fd_in, STDIN_FILENO);
|
||||
if (cmd->fd_out != 1)
|
||||
dup2(cmd->fd_out, STDOUT_FILENO);
|
||||
close_fd(cmd, pid);
|
||||
execve(cmd->argv[0], cmd->argv, envp);
|
||||
}
|
||||
else
|
||||
{
|
||||
close_fd(cmd, pid);
|
||||
// if (cmd->fd_in != 0)
|
||||
// close(cmd->fd_in);
|
||||
// if (cmd->fd_out != 1 && cmd->fd_redirect == 1)
|
||||
// close(cmd->fd_out);
|
||||
}
|
||||
while ((wpid = wait(&status)) > 0);
|
||||
cmd_list = cmd_list->next;
|
||||
}
|
||||
}
|
||||
|
||||
void shell_loop(t_all *c)
|
||||
{
|
||||
char *line_input;
|
||||
t_list *cmd;
|
||||
|
||||
line_input = NULL;
|
||||
while (1)
|
||||
{
|
||||
if (line_input)
|
||||
free(line_input);
|
||||
line_input = readline(c->prompt);
|
||||
if (line_input && *line_input)
|
||||
{
|
||||
cmd = parser(line_input, c->envp);
|
||||
exec_cmd(c->envp, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wip_test()
|
||||
{
|
||||
char term_desc[2048];
|
||||
char *term_type;
|
||||
int term_width;
|
||||
int term_height;
|
||||
int ret;
|
||||
|
||||
term_type = getenv("TERM");
|
||||
if (term_type == 0)
|
||||
ft_putstr_fd("Specify a terminal type with `setenv TERM <yourtype>'.\n", 2);
|
||||
ret = tgetent(term_desc, term_type);
|
||||
if (ret < 0)
|
||||
ft_putstr_fd("Could not access the termcap data base.\n", 2);
|
||||
if (ret == 0)
|
||||
ft_putstr_fd("Terminal type `%s' is not defined.\n", 2);
|
||||
term_height = tgetnum ("li");
|
||||
term_width = tgetnum ("co");
|
||||
/* Extract information that termcap functions use. */
|
||||
/* temp = tgetstr ("pc", BUFFADDR);
|
||||
PC = temp ? *temp : 0;
|
||||
BC = tgetstr ("le", BUFFADDR);
|
||||
UP = tgetstr ("up", BUFFADDR); */
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
t_all c;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if (!init(&c, envp))
|
||||
exit(EXIT_FAILURE);
|
||||
shell_loop(&c);
|
||||
if (!init(&c, argv))
|
||||
exit_free(&c, EXIT_FAILURE);
|
||||
if (c.script_fd)
|
||||
shell_script(&c, c.script_fd);
|
||||
else if (!isatty(STDIN_FILENO))
|
||||
shell_script(&c, STDIN_FILENO);
|
||||
else
|
||||
shell_loop(&c);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
52
srcs/misc/error_wrappers.c
Normal file
52
srcs/misc/error_wrappers.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* error_wrappers.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/12/01 17:16:30 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/16 04:38:05 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int shell_error(char *s1, char *s2, char *s3, int ret_val)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
prefix = "minishell: ";
|
||||
write(STDERR_FILENO, prefix, ft_strlen(prefix));
|
||||
if (s1)
|
||||
write(STDERR_FILENO, s1, ft_strlen(s1));
|
||||
if (s2)
|
||||
write(STDERR_FILENO, s2, ft_strlen(s2));
|
||||
if (s3)
|
||||
write(STDERR_FILENO, s3, ft_strlen(s3));
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int shell_perror(char *s1, char *s2, char *s3, int ret_val)
|
||||
{
|
||||
char *prefix;
|
||||
|
||||
prefix = "minishell: ";
|
||||
write(STDERR_FILENO, prefix, ft_strlen(prefix));
|
||||
if (s1)
|
||||
write(STDERR_FILENO, s1, ft_strlen(s1));
|
||||
if (s2)
|
||||
write(STDERR_FILENO, s2, ft_strlen(s2));
|
||||
if (s3)
|
||||
write(STDERR_FILENO, s3, ft_strlen(s3));
|
||||
perror(NULL);
|
||||
return (ret_val);
|
||||
}
|
||||
|
||||
int ft_reti_perror_io(int ret, char *err_str, char *io_file)
|
||||
{
|
||||
ft_putstr_fd(err_str, STDERR_FILENO);
|
||||
perror(io_file);
|
||||
return (ret);
|
||||
}
|
||||
98
srcs/misc/free.c
Normal file
98
srcs/misc/free.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* free.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/21 12:14:43 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int exit_free(t_all *c, int exit_status)
|
||||
{
|
||||
free(c->prompt_base);
|
||||
free(c->prompt);
|
||||
ft_lstclear((t_list **)&c->token_list, free);
|
||||
ft_free_2d_arr(environ);
|
||||
ft_free_2d_arr(c->path);
|
||||
free_pipeline(&c->pipeline);
|
||||
if (c->script_fd)
|
||||
{
|
||||
if (c->script_fd > 0)
|
||||
{
|
||||
gnl(c->script_fd, NULL, 1);
|
||||
if (close(c->script_fd) == -1)
|
||||
perror("close()");
|
||||
}
|
||||
}
|
||||
else if (!isatty(STDIN_FILENO))
|
||||
gnl(STDIN_FILENO, NULL, 1);
|
||||
else
|
||||
rl_clear_history();
|
||||
close_stdio();
|
||||
exit(exit_status);
|
||||
}
|
||||
|
||||
void free_pipeline(t_cmd **pipeline_ptr[])
|
||||
{
|
||||
int i;
|
||||
t_cmd **pipeline;
|
||||
|
||||
pipeline = *pipeline_ptr;
|
||||
if (!pipeline)
|
||||
return ;
|
||||
close_pipeline_fd(pipeline);
|
||||
i = 0;
|
||||
while (pipeline[i])
|
||||
{
|
||||
ft_free_2d_arr(pipeline[i]->argv);
|
||||
free(pipeline[i]->path);
|
||||
i++;
|
||||
}
|
||||
ft_free_2d_arr(pipeline);
|
||||
*pipeline_ptr = NULL;
|
||||
}
|
||||
|
||||
void close_pipeline_fd(t_cmd *pipeline[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!pipeline)
|
||||
return ;
|
||||
i = 0;
|
||||
while (pipeline[i])
|
||||
{
|
||||
close_cmd_fd(pipeline[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void close_cmd_fd(t_cmd *cmd)
|
||||
{
|
||||
if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0)
|
||||
{
|
||||
if (close(cmd->fd_in) == -1)
|
||||
perror("close()");
|
||||
cmd->fd_in = 0;
|
||||
}
|
||||
if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0)
|
||||
{
|
||||
if (close(cmd->fd_out) == -1)
|
||||
perror("close()");
|
||||
cmd->fd_out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void close_stdio(void)
|
||||
{
|
||||
if (close(STDIN_FILENO) == -1)
|
||||
perror("close()");
|
||||
if (close(STDOUT_FILENO) == -1)
|
||||
perror("close()");
|
||||
if (close(STDERR_FILENO) == -1)
|
||||
perror("close()");
|
||||
}
|
||||
27
srcs/misc/last_exit_status.c
Normal file
27
srcs/misc/last_exit_status.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* last_exit_status.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/26 19:02:27 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 16:48:02 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int set_last_exit_status(int new_value)
|
||||
{
|
||||
static int last_exit_status = 0;
|
||||
|
||||
if (new_value >= 0)
|
||||
last_exit_status = new_value;
|
||||
return (last_exit_status);
|
||||
}
|
||||
|
||||
int get_last_exit_status(void)
|
||||
{
|
||||
return (set_last_exit_status(-1));
|
||||
}
|
||||
35
srcs/misc/retrieve_path.c
Normal file
35
srcs/misc/retrieve_path.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* retrieve_path.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 19:28:49 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
#define WARNING_PATH "Warning, $PATH not set\n"
|
||||
|
||||
int retrieve_path(char **path_stock[])
|
||||
{
|
||||
char *path;
|
||||
char **path_split;
|
||||
|
||||
path = getenv("PATH");
|
||||
if (!path)
|
||||
{
|
||||
ft_free_2d_arr(*path_stock);
|
||||
*path_stock = NULL;
|
||||
return (shell_error(WARNING_PATH, "", "", 0));
|
||||
}
|
||||
path_split = ft_split(path, ':');
|
||||
if (!path_split)
|
||||
return (ft_reti_perror(-1, "retrieve_path()"));
|
||||
ft_free_2d_arr(*path_stock);
|
||||
*path_stock = path_split;
|
||||
return (1);
|
||||
}
|
||||
39
srcs/misc/signals.c
Normal file
39
srcs/misc/signals.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* signals.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/23 18:56:53 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/18 14:21:47 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void sigint_handler_interactive(int signum)
|
||||
{
|
||||
write(1, "\n", 1);
|
||||
rl_on_new_line();
|
||||
rl_replace_line("", 1);
|
||||
rl_redisplay();
|
||||
set_last_exit_status(EXIT_SIGNAL + signum);
|
||||
}
|
||||
|
||||
void sigint_handler_heredoc(int signum)
|
||||
{
|
||||
(void)signum;
|
||||
rl_done = 1;
|
||||
g_switch_heredoc_sigint = 1;
|
||||
}
|
||||
|
||||
void set_signals_behaviour(void)
|
||||
{
|
||||
struct sigaction signal_behaviour;
|
||||
|
||||
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
|
||||
signal_behaviour.sa_handler = SIG_IGN;
|
||||
sigaction(SIGQUIT, &signal_behaviour, NULL);
|
||||
sigaction(SIGINT, &signal_behaviour, NULL);
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void **cmd_path(char **argv, char **envp)
|
||||
{
|
||||
int i;
|
||||
char **path;
|
||||
char *cmd;
|
||||
|
||||
i = 0;
|
||||
while (envp[i] && ft_strncmp(envp[i], "PATH=", 5))
|
||||
i++;
|
||||
path = ft_split(envp[i] + 5, ':'); // 5 = lentgh of "PATH="
|
||||
i = -1;
|
||||
while (*path && i != 0)
|
||||
{
|
||||
cmd = ft_strjoin(path[0], "/");
|
||||
cmd = ft_strjoin(cmd, argv[0]);
|
||||
i = access(cmd, X_OK);
|
||||
path++;
|
||||
}
|
||||
argv[0] = cmd;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int handle_fd(char **input, int i, int fdin, t_cmd *cmd)
|
||||
{
|
||||
int *pipes_fd;
|
||||
int next_in;
|
||||
char *tmp;
|
||||
|
||||
cmd->fd_in = fdin;
|
||||
cmd->fd_out = 1;
|
||||
cmd->fd_redirect = 1;
|
||||
cmd->pipe_in = 0;
|
||||
cmd->pipe_out = 1;
|
||||
next_in = 0;
|
||||
if (input[i + 1])
|
||||
{
|
||||
pipes_fd = calloc(2, sizeof(int));
|
||||
pipe(pipes_fd);
|
||||
cmd->fd_out = pipes_fd[1];
|
||||
next_in = pipes_fd[0];
|
||||
cmd->pipe_in = pipes_fd[0];
|
||||
cmd->pipe_out = pipes_fd[1];
|
||||
}
|
||||
tmp = ft_strchr(input[i], '>');
|
||||
if (tmp)
|
||||
{
|
||||
tmp[0] = '\0';
|
||||
tmp = ft_strtrim(tmp + 2, " "); // +2 for "> "
|
||||
cmd->fd_out = open(tmp, O_RDWR | O_TRUNC);
|
||||
next_in = cmd->fd_out;
|
||||
cmd->fd_redirect = cmd->fd_out;
|
||||
}
|
||||
return (next_in);
|
||||
}
|
||||
|
||||
t_list *parser(char *input, char **envp)
|
||||
{
|
||||
t_list *cmd;
|
||||
t_cmd *element;
|
||||
char **input_split;
|
||||
int i;
|
||||
int tmp_fd;
|
||||
|
||||
input_split = ft_split(input, '|');
|
||||
tmp_fd = 0;
|
||||
i = 0;
|
||||
cmd = NULL;
|
||||
while (input_split[i])
|
||||
{
|
||||
element = calloc(1, sizeof(t_cmd));
|
||||
tmp_fd = handle_fd(input_split, i, tmp_fd, element);
|
||||
element->argv = ft_split(input_split[i], ' ');
|
||||
element->builtin = cmd_path(element->argv, envp);
|
||||
ft_lstadd_back(&cmd, ft_lstnew(element));
|
||||
i++;
|
||||
}
|
||||
return (cmd);
|
||||
}
|
||||
95
srcs/parsing/create_pipeline.c
Normal file
95
srcs/parsing/create_pipeline.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* create_pipeline.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/02 22:46:23 by lperrey #+# #+# */
|
||||
/* Updated: 2021/11/29 12:29:27 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static size_t cmd_words_count(t_token *t);
|
||||
|
||||
size_t count_pipes(t_token *t)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
count = 0;
|
||||
while (t)
|
||||
{
|
||||
if (t->id == T_PIPE)
|
||||
count++;
|
||||
t = t->next;
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
|
||||
t_cmd **pipeline_alloc(size_t cmd_nbr)
|
||||
{
|
||||
t_cmd **pipeline;
|
||||
size_t i;
|
||||
|
||||
pipeline = ft_calloc(cmd_nbr + 1, sizeof (void *));
|
||||
if (!pipeline)
|
||||
return (ft_retp_perror(NULL, "pipeline_alloc()"));
|
||||
i = 0;
|
||||
while (i < cmd_nbr)
|
||||
{
|
||||
pipeline[i] = ft_calloc(1, sizeof (*pipeline[i]));
|
||||
if (!pipeline[i])
|
||||
{
|
||||
ft_free_2d_arr(pipeline);
|
||||
return (ft_retp_perror(NULL, "pipeline_alloc()"));
|
||||
}
|
||||
pipeline[i]->fd_in = STDIN_FILENO;
|
||||
pipeline[i]->fd_out = STDOUT_FILENO;
|
||||
i++;
|
||||
}
|
||||
return (pipeline);
|
||||
}
|
||||
|
||||
int pipeline_fill_argv(t_token *t, t_cmd **pipeline)
|
||||
{
|
||||
size_t i;
|
||||
size_t arg_i;
|
||||
|
||||
i = 0;
|
||||
while (pipeline[i])
|
||||
{
|
||||
pipeline[i]->argv = ft_calloc(cmd_words_count(t) + 1, sizeof (char *));
|
||||
if (!pipeline[i]->argv)
|
||||
return (ft_reti_perror(0, "pipeline_fill_argv()"));
|
||||
arg_i = 0;
|
||||
while (t && t->id != '|')
|
||||
{
|
||||
if (t->id == T_WORD)
|
||||
{
|
||||
pipeline[i]->argv[arg_i++] = t->content;
|
||||
t->content = NULL;
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
if (t && t->id == '|')
|
||||
t = t->next;
|
||||
i++;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static size_t cmd_words_count(t_token *t)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
count = 0;
|
||||
while (t && t->id != '|')
|
||||
{
|
||||
if (t->id == T_WORD)
|
||||
count++;
|
||||
t = t->next;
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
52
srcs/parsing/expansions/content_copy.c
Normal file
52
srcs/parsing/expansions/content_copy.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* content_copy.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/21 01:04:58 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static void quotes_handling(char c, int *quotes_state);
|
||||
|
||||
t_list *content_copy(char *content, int *i, int *quotes_state)
|
||||
{
|
||||
int i_exp;
|
||||
t_list *expand;
|
||||
|
||||
expand = ft_lstnew_generic(sizeof(t_list), ft_strlen(&content[*i]) + 1);
|
||||
if (!expand)
|
||||
return (NULL);
|
||||
i_exp = 0;
|
||||
while (content[*i])
|
||||
{
|
||||
if (content[*i] == '$' && *quotes_state != IN_QUOTES)
|
||||
break ;
|
||||
quotes_handling(content[*i], quotes_state);
|
||||
((char *)expand->content)[i_exp++] = content[(*i)++];
|
||||
}
|
||||
return (expand);
|
||||
}
|
||||
|
||||
static void quotes_handling(char c, int *quotes_state)
|
||||
{
|
||||
if (c == '\'' && *quotes_state != IN_DQUOTES)
|
||||
{
|
||||
if (*quotes_state == IN_QUOTES)
|
||||
*quotes_state = 0;
|
||||
else
|
||||
*quotes_state = IN_QUOTES;
|
||||
}
|
||||
else if (c == '\"' && *quotes_state != IN_QUOTES)
|
||||
{
|
||||
if (*quotes_state == IN_DQUOTES)
|
||||
*quotes_state = 0;
|
||||
else
|
||||
*quotes_state = IN_DQUOTES;
|
||||
}
|
||||
}
|
||||
82
srcs/parsing/expansions/content_expand.c
Normal file
82
srcs/parsing/expansions/content_expand.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* content_expand.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/21 01:20:40 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static char *env_var_expansion(char *content, int *i);
|
||||
static char *retrieve_var(char *content, int *i);
|
||||
|
||||
t_list *content_expand(char *content, int *i)
|
||||
{
|
||||
t_list *expand;
|
||||
|
||||
expand = ft_lstnew(NULL);
|
||||
if (!expand)
|
||||
return (NULL);
|
||||
expand->content = env_var_expansion(content, i);
|
||||
if (!expand->content)
|
||||
{
|
||||
free(expand);
|
||||
return (NULL);
|
||||
}
|
||||
return (expand);
|
||||
}
|
||||
|
||||
static char *env_var_expansion(char *content, int *i)
|
||||
{
|
||||
char *expansion;
|
||||
|
||||
(*i)++;
|
||||
if (content[*i] == '?')
|
||||
{
|
||||
(*i)++;
|
||||
expansion = ft_itoa(get_last_exit_status());
|
||||
}
|
||||
else if (content[*i] == '_' || ft_isalpha(content[*i]))
|
||||
expansion = retrieve_var(content, i);
|
||||
else
|
||||
{
|
||||
expansion = ft_calloc(1 + 1, 1);
|
||||
if (!expansion)
|
||||
return (NULL);
|
||||
expansion[0] = '$';
|
||||
}
|
||||
return (expansion);
|
||||
}
|
||||
|
||||
static char *retrieve_var(char *content, int *i)
|
||||
{
|
||||
char *expansion;
|
||||
char *tmp;
|
||||
int i_exp;
|
||||
|
||||
expansion = ft_calloc(ft_strlen(&content[*i - 1]) + 1, 1);
|
||||
if (!expansion)
|
||||
return (NULL);
|
||||
i_exp = 0;
|
||||
while (content[*i] == '_' || ft_isalnum(content[*i]))
|
||||
expansion[i_exp++] = content[(*i)++];
|
||||
tmp = getenv(expansion);
|
||||
ft_free_null(&expansion);
|
||||
if (tmp)
|
||||
expansion = ft_strdup(tmp);
|
||||
else
|
||||
expansion = ft_calloc(1, 1);
|
||||
return (expansion);
|
||||
}
|
||||
|
||||
/*
|
||||
environment variables must be POSIX NAME :
|
||||
3.235 Name
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
|
||||
#tag_03_235
|
||||
*/
|
||||
43
srcs/parsing/expansions/expand_token.c
Normal file
43
srcs/parsing/expansions/expand_token.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* expand_token.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/21 01:12:42 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
t_list *content_copy(char *content, int *i, int *quotes_state);
|
||||
t_list *content_expand(char *content, int *i);
|
||||
|
||||
t_list *expand_token(char *content)
|
||||
{
|
||||
int quotes_state;
|
||||
int i;
|
||||
t_list head;
|
||||
t_list *expand;
|
||||
|
||||
head.next = NULL;
|
||||
expand = &head;
|
||||
quotes_state = 0;
|
||||
i = 0;
|
||||
while (content[i])
|
||||
{
|
||||
if (content[i] == '$')
|
||||
expand->next = content_expand(content, &i);
|
||||
else
|
||||
expand->next = content_copy(content, &i, "es_state);
|
||||
expand = expand->next;
|
||||
if (!expand)
|
||||
{
|
||||
perror("expand_token() error");
|
||||
return (ft_lstclear(&head.next, free));
|
||||
}
|
||||
}
|
||||
return (head.next);
|
||||
}
|
||||
82
srcs/parsing/expansions/expansions.c
Normal file
82
srcs/parsing/expansions/expansions.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* expansions.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 15:51:18 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
t_list *expand_token(char *content);
|
||||
char *rejoin_after_expand(t_list *expand_lst);
|
||||
int new_token_for_each_field(char **fields, t_token *t);
|
||||
|
||||
/*
|
||||
* 1 - chaque bout dans un element d'une t_list
|
||||
* (telle quelle si non expand, ou VARIABLE de env)
|
||||
* 2 - strjoin() le tout
|
||||
* 3 - split avec un ft_strplit() modifié (ne splitant pas dans les quotes)
|
||||
* 4 - quotes removal, ft_strdup_quotes() le tableau split
|
||||
* 5 - creer un token T_WORD pour chaque *string du **split_arr
|
||||
* (ft_lstadd_front() sur le token original, puis set le token orignal à :
|
||||
* t->id = 0 ;
|
||||
* free(t->content) ;
|
||||
* t->content = NULL ;
|
||||
* pour qu'il soit ignoré sur la suite du parsing)
|
||||
*/
|
||||
|
||||
int expansions(t_token *t, t_cmd **pipeline)
|
||||
{
|
||||
int i;
|
||||
t_token *next_token;
|
||||
|
||||
i = 0;
|
||||
while (t)
|
||||
{
|
||||
if (t->id == '|')
|
||||
i++;
|
||||
if (!pipeline[i]->error && t->id == T_WORD)
|
||||
{
|
||||
next_token = t->next;
|
||||
if (!token_expansions(t))
|
||||
{
|
||||
pipeline[i]->error = EXIT_EXPANSION;
|
||||
}
|
||||
while (t != next_token)
|
||||
t = t->next;
|
||||
}
|
||||
else
|
||||
t = t->next;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
int token_expansions(t_token *t)
|
||||
{
|
||||
void *tmp;
|
||||
char **tmp_split;
|
||||
|
||||
tmp = (t_list *)expand_token(t->content);
|
||||
if (!tmp)
|
||||
return (0);
|
||||
tmp = (char *)rejoin_after_expand(tmp);
|
||||
if (!tmp)
|
||||
return (0);
|
||||
tmp_split = ft_split_quotes(tmp, ' ');
|
||||
free(tmp);
|
||||
if (!tmp_split)
|
||||
return (0);
|
||||
tmp = tmp_split;
|
||||
tmp_split = ft_dup_2d_arr(tmp_split, (t_dup_f)ft_strdup_quotes);
|
||||
ft_free_2d_arr(tmp);
|
||||
if (!tmp_split)
|
||||
return (0);
|
||||
if (!new_token_for_each_field(tmp_split, t))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
59
srcs/parsing/expansions/new_token_for_each_field.c
Normal file
59
srcs/parsing/expansions/new_token_for_each_field.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* new_token_for_each_field.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 17:22:41 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static void insert_tokens(t_token *t, t_token *insert_lst);
|
||||
|
||||
int new_token_for_each_field(char **fields, t_token *t)
|
||||
{
|
||||
t_token head;
|
||||
t_token *insert_lst;
|
||||
int i;
|
||||
|
||||
head.next = NULL;
|
||||
insert_lst = &head;
|
||||
i = 0;
|
||||
while (fields[i])
|
||||
{
|
||||
insert_lst->next = ft_lstnew_generic(sizeof(t_token), 0);
|
||||
insert_lst = insert_lst->next;
|
||||
if (!insert_lst)
|
||||
{
|
||||
perror("insert_token_for_each_field() error");
|
||||
ft_free_2d_arr(fields);
|
||||
ft_lstclear((t_list **)&head.next, NULL);
|
||||
return (0);
|
||||
}
|
||||
insert_lst->content = fields[i];
|
||||
insert_lst->id = T_WORD;
|
||||
i++;
|
||||
}
|
||||
free(fields);
|
||||
insert_tokens(t, head.next);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void insert_tokens(t_token *t, t_token *insert_lst)
|
||||
{
|
||||
t_token *tmp;
|
||||
t_token *insert_lst_last;
|
||||
|
||||
t->id = 0;
|
||||
ft_free_null(&t->content);
|
||||
if (!insert_lst)
|
||||
return ;
|
||||
tmp = t->next;
|
||||
t->next = insert_lst;
|
||||
insert_lst_last = (t_token *)ft_lstlast((t_list *)insert_lst);
|
||||
insert_lst_last->next = tmp;
|
||||
}
|
||||
34
srcs/parsing/expansions/rejoin_after_expand.c
Normal file
34
srcs/parsing/expansions/rejoin_after_expand.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* rejoin_after_expand.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/20 14:55:03 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
char *rejoin_after_expand(t_list *expand_lst)
|
||||
{
|
||||
t_list *head;
|
||||
char *result;
|
||||
|
||||
head = expand_lst;
|
||||
result = NULL;
|
||||
while (expand_lst)
|
||||
{
|
||||
result = ft_strjoinfree_s1(result, expand_lst->content);
|
||||
if (!result)
|
||||
{
|
||||
perror("rejoin_after_expand() error");
|
||||
return (ft_lstclear(&head, free));
|
||||
}
|
||||
expand_lst = expand_lst->next;
|
||||
}
|
||||
ft_lstclear(&head, free);
|
||||
return (result);
|
||||
}
|
||||
115
srcs/parsing/parsing.c
Normal file
115
srcs/parsing/parsing.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* parsing.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 13:53:19 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
void save_redirections_words(t_token *t);
|
||||
|
||||
t_cmd **parsing(t_token *token_list, int script_fd)
|
||||
{
|
||||
t_cmd **pipeline;
|
||||
|
||||
if (!valid_syntax(token_list))
|
||||
return (NULL);
|
||||
save_redirections_words(token_list);
|
||||
pipeline = pipeline_alloc(1 + count_pipes(token_list));
|
||||
if (!pipeline)
|
||||
return (NULL);
|
||||
if (!expansions(token_list, pipeline))
|
||||
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
|
||||
if (!redirections(token_list, pipeline, script_fd))
|
||||
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
|
||||
if (!pipeline_fill_argv(token_list, pipeline))
|
||||
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
|
||||
return (pipeline);
|
||||
}
|
||||
|
||||
void save_redirections_words(t_token *t)
|
||||
{
|
||||
while (t)
|
||||
{
|
||||
if (t->id == '>' || t->id == T_DGREAT
|
||||
|| t->id == '<' || t->id == T_DLESS)
|
||||
{
|
||||
t = t->next;
|
||||
t->id = T_REDIRECTION_WORD;
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
2.9.1 Simple Commands
|
||||
2.9.1 - 1) Save Words
|
||||
2.9.1 - 2) Expansion
|
||||
2.9.1 - 3) Redirection
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
#tag_18_09_01
|
||||
*/
|
||||
|
||||
/*
|
||||
2.10 Shell Grammar
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
#tag_18_10
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------
|
||||
The grammar symbols
|
||||
------------------------------------------------------- */
|
||||
/*
|
||||
%token WORD
|
||||
%token LESS // '<'
|
||||
%token GREAT // '>'
|
||||
%token DLESS // '<<'
|
||||
%token DGREAT // '>>'
|
||||
%token PIPE // '|'
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------
|
||||
The Simplified Grammar
|
||||
------------------------------------------------------- */
|
||||
/*
|
||||
%start program
|
||||
%%
|
||||
pipeline : command
|
||||
| pipeline '|' command
|
||||
;
|
||||
command : cmd_prefix cmd_name cmd_suffix
|
||||
| cmd_prefix cmd_name
|
||||
| cmd_name cmd_suffix
|
||||
| cmd_name
|
||||
| cmd_prefix
|
||||
;
|
||||
cmd_name : WORD // Apply rule 7a
|
||||
;
|
||||
cmd_prefix : io_redirect
|
||||
| cmd_prefix io_redirect
|
||||
;
|
||||
cmd_suffix : io_redirect
|
||||
| cmd_suffix io_redirect
|
||||
| WORD
|
||||
| cmd_suffix WORD
|
||||
;
|
||||
io_redirect : io_file
|
||||
| io_here
|
||||
;
|
||||
io_file : '<' filename
|
||||
| '>' filename
|
||||
| DGREAT filename
|
||||
;
|
||||
filename : WORD // Apply rule 2
|
||||
;
|
||||
io_here : DLESS here_end
|
||||
;
|
||||
here_end : WORD // Apply rule 3
|
||||
;
|
||||
*/
|
||||
165
srcs/parsing/redirections/here_doc.c
Normal file
165
srcs/parsing/redirections/here_doc.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* here_doc.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 17:04:47 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int here_doc_write(char *delimiter, int doc_fd, int script_fd);
|
||||
static int here_doc_write_interactive(char *delimiter, int doc_fd);
|
||||
static int here_doc_write_script(char *delimiter, int doc_fd, int script_fd);
|
||||
static int event_hook_empty(void);
|
||||
|
||||
#define TMP_HERE_DOC "/tmp/minishell_here_doc"
|
||||
#define WARNING_EOF "warning: here-document delimited by end-of-file (wanted `"
|
||||
|
||||
int here_doc(char *delimiter, int script_fd)
|
||||
{
|
||||
int here_doc;
|
||||
int ret;
|
||||
|
||||
delimiter = ft_strdup_quotes(delimiter);
|
||||
if (!delimiter)
|
||||
return (ft_reti_perror(-1, "ft_strdup_quotes()"));
|
||||
here_doc = open(TMP_HERE_DOC, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
|
||||
if (here_doc == -1)
|
||||
return (ft_reti_perror_io(-1, "open() ", TMP_HERE_DOC));
|
||||
ret = here_doc_write(delimiter, here_doc, script_fd);
|
||||
free(delimiter);
|
||||
if (close(here_doc) == -1)
|
||||
shell_perror(TMP_HERE_DOC, ": ", "", 0);
|
||||
if (ret != 0)
|
||||
{
|
||||
if (unlink(TMP_HERE_DOC) == -1)
|
||||
return (ft_reti_perror_io(ret, "unlink() ", TMP_HERE_DOC));
|
||||
return (ret);
|
||||
}
|
||||
here_doc = open(TMP_HERE_DOC, O_RDONLY);
|
||||
if (here_doc == -1)
|
||||
shell_perror(TMP_HERE_DOC, ": ", "", 0);
|
||||
if (unlink(TMP_HERE_DOC) == -1)
|
||||
return (ft_reti_perror_io(-1, "unlink() ", TMP_HERE_DOC));
|
||||
return (here_doc);
|
||||
}
|
||||
|
||||
static int here_doc_write(char *delimiter, int doc_fd, int script_fd)
|
||||
{
|
||||
int ret;
|
||||
struct sigaction signal_action;
|
||||
|
||||
if (script_fd || !isatty(STDIN_FILENO))
|
||||
{
|
||||
ret = here_doc_write_script(delimiter, doc_fd, script_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
ft_bzero(&signal_action, sizeof(signal_action));
|
||||
signal_action.sa_handler = sigint_handler_heredoc;
|
||||
sigaction(SIGINT, &signal_action, NULL);
|
||||
rl_event_hook = event_hook_empty;
|
||||
ret = here_doc_write_interactive(delimiter, doc_fd);
|
||||
rl_event_hook = NULL;
|
||||
signal_action.sa_handler = SIG_IGN;
|
||||
sigaction(SIGINT, &signal_action, NULL);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int here_doc_write_interactive(char *delimiter, int doc_fd)
|
||||
{
|
||||
char *line;
|
||||
size_t line_len;
|
||||
|
||||
line = NULL;
|
||||
g_switch_heredoc_sigint = 0;
|
||||
while (1)
|
||||
{
|
||||
line = readline("> ");
|
||||
if (g_switch_heredoc_sigint == 1)
|
||||
return (set_last_exit_status(EXIT_SIGNAL + SIGINT));
|
||||
if (!line)
|
||||
return (shell_error(WARNING_EOF, delimiter, "')", 0));
|
||||
line_len = ft_strlen(line);
|
||||
if (ft_strncmp(line, delimiter, line_len + 1) == 0)
|
||||
break ;
|
||||
if (write(doc_fd, line, line_len) == -1)
|
||||
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
|
||||
if (write(doc_fd, "\n", 1) == -1)
|
||||
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
|
||||
ft_free_null(&line);
|
||||
}
|
||||
free(line);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int here_doc_write_script(char *delimiter, int doc_fd, int script_fd)
|
||||
{
|
||||
char *line;
|
||||
int ret;
|
||||
size_t line_len;
|
||||
|
||||
line = NULL;
|
||||
ret = 1;
|
||||
while (ret)
|
||||
{
|
||||
ret = gnl(script_fd, &line, 0);
|
||||
if (ret == -1)
|
||||
return (ft_reti_perror_free(-1, line, free, "gnl() script_fd"));
|
||||
line_len = ft_strlen(line);
|
||||
if (ft_strncmp(line, delimiter, line_len + 1) == 0)
|
||||
break ;
|
||||
if (write(doc_fd, line, line_len) == -1)
|
||||
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
|
||||
if ((ret || line[0]) && write(doc_fd, "\n", 1) == -1)
|
||||
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
|
||||
ft_free_null(&line);
|
||||
}
|
||||
if (!line && ret == 0)
|
||||
shell_error(WARNING_EOF, delimiter, "')", 0);
|
||||
free(line);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int event_hook_empty(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
#tag_18_07_04
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||
#tag_18_02
|
||||
*/
|
||||
/* If any part of word is quoted,
|
||||
the delimiter shall be formed by performing quote removal on word,
|
||||
and the here-document lines shall not be expanded.
|
||||
Otherwise, the delimiter shall be the word itself. */
|
||||
// TODO Bonus: expansions in here_doc.
|
||||
|
||||
/*
|
||||
** rl_done
|
||||
** Setting this to a non-zero value causes Readline
|
||||
** to return the current line immediately.
|
||||
** rl_event_hook
|
||||
** If non-zero, this is the address of a function to call periodically
|
||||
** when Readline is waiting for terminal input.
|
||||
** By default, this will be called at most
|
||||
** ten times a second if there is no keyboard input.
|
||||
**
|
||||
** https://stackoverflow.com/questions/53165704/
|
||||
** readline-c-force-return-of-certain-text-in-readline
|
||||
** "rl_done is only checked in the event loop. When you give it
|
||||
** a null event hook function, it checks the rl_done and exits"
|
||||
**
|
||||
** rl_signal_event_hook
|
||||
** If non-zero, this is the address of a function to call if a read
|
||||
** system call is interrupted when Readline is reading terminal input.
|
||||
*/
|
||||
138
srcs/parsing/redirections/redirections.c
Normal file
138
srcs/parsing/redirections/redirections.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* redirections.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 14:00:33 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int here_doc(char *delimiter, int script_fd);
|
||||
|
||||
static int redirect_cmd_input(t_token *t, t_cmd *cmd);
|
||||
static int redirect_cmd_heredoc(t_token *t, t_cmd *cmd, int script_fd);
|
||||
static int redirect_cmd_output(t_token *t, t_cmd *cmd);
|
||||
static int expand_redirection(t_token *t);
|
||||
|
||||
int redirections(t_token *t, t_cmd **pipeline, int script_fd)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (t)
|
||||
{
|
||||
if (t->id == '|')
|
||||
i++;
|
||||
if (!pipeline[i]->error)
|
||||
{
|
||||
if (t->id == '<' && !redirect_cmd_input(t, pipeline[i]))
|
||||
return (0);
|
||||
else if (t->id == T_DLESS
|
||||
&& !redirect_cmd_heredoc(t, pipeline[i], script_fd))
|
||||
return (0);
|
||||
else if (t->id == '>' || t->id == T_DGREAT)
|
||||
if (!redirect_cmd_output(t, pipeline[i]))
|
||||
return (0);
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int redirect_cmd_input(t_token *t, t_cmd *cmd)
|
||||
{
|
||||
if (cmd->fd_in != STDIN_FILENO)
|
||||
if (close(cmd->fd_in) == -1)
|
||||
perror("close()");
|
||||
if (!expand_redirection(t))
|
||||
{
|
||||
cmd->error = EXIT_REDIRECTION;
|
||||
return (1);
|
||||
}
|
||||
cmd->fd_in = open(t->next->content, O_RDONLY);
|
||||
if (cmd->fd_in == -1)
|
||||
{
|
||||
shell_perror(t->next->content, ": ", "", 0);
|
||||
cmd->error = EXIT_REDIRECTION;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int redirect_cmd_heredoc(t_token *t, t_cmd *cmd, int script_fd)
|
||||
{
|
||||
if (cmd->fd_in != STDIN_FILENO)
|
||||
if (close(cmd->fd_in) == -1)
|
||||
perror("close()");
|
||||
cmd->fd_in = here_doc(t->next->content, script_fd);
|
||||
if (cmd->fd_in == -1)
|
||||
{
|
||||
shell_error("heredoc error", ": ", "", 0);
|
||||
cmd->error = EXIT_REDIRECTION;
|
||||
}
|
||||
else if (cmd->fd_in > EXIT_SIGNAL)
|
||||
{
|
||||
cmd->fd_in = 0;
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int redirect_cmd_output(t_token *t, t_cmd *cmd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if (cmd->fd_out != STDOUT_FILENO)
|
||||
if (close(cmd->fd_out) == -1)
|
||||
perror("close()");
|
||||
if (!expand_redirection(t))
|
||||
{
|
||||
cmd->error = EXIT_REDIRECTION;
|
||||
return (1);
|
||||
}
|
||||
flags = O_WRONLY | O_CREAT;
|
||||
if (t->id == '>')
|
||||
flags = flags | O_TRUNC;
|
||||
else if (t->id == T_DGREAT)
|
||||
flags = flags | O_APPEND;
|
||||
cmd->fd_out = open(t->next->content, flags, S_IRWXU);
|
||||
if (cmd->fd_out == -1)
|
||||
{
|
||||
shell_perror(t->next->content, ": ", "", EXIT_REDIRECTION);
|
||||
cmd->error = EXIT_REDIRECTION;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int expand_redirection(t_token *t)
|
||||
{
|
||||
t_token *head;
|
||||
t_token *next_token;
|
||||
int ret;
|
||||
|
||||
ret = 1;
|
||||
head = t;
|
||||
t = t->next;
|
||||
next_token = t->next;
|
||||
t->next = NULL;
|
||||
if (!token_expansions(t))
|
||||
{
|
||||
((t_token *)ft_lstlast((t_list *)head))->next = next_token;
|
||||
return (0);
|
||||
}
|
||||
head->next = t->next;
|
||||
free(t);
|
||||
if (head->next)
|
||||
head->next->id = T_REDIRECTION_WORD;
|
||||
if (ft_lstsize((t_list *)head->next) != 1)
|
||||
{
|
||||
ret = 0;
|
||||
shell_error("", "", "ambiguous redirect", 0);
|
||||
}
|
||||
((t_token *)ft_lstlast((t_list *)head))->next = next_token;
|
||||
return (ret);
|
||||
}
|
||||
83
srcs/parsing/valid_syntax/rules_command.c
Normal file
83
srcs/parsing/valid_syntax/rules_command.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* rules_command.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 22:11:40 by hulamy ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int valid_io_redirect(t_token **token_list);
|
||||
|
||||
// cmd_prefix cmd_name cmd_suffix
|
||||
int valid_command_rule1(t_token **token_list)
|
||||
{
|
||||
if (!valid_io_redirect(token_list))
|
||||
return (0);
|
||||
while (valid_io_redirect(token_list))
|
||||
continue ;
|
||||
if (!valid_token(token_list, T_WORD))
|
||||
return (0);
|
||||
if (!valid_token(token_list, T_WORD) && !valid_io_redirect(token_list))
|
||||
return (0);
|
||||
while (valid_token(token_list, T_WORD) || valid_io_redirect(token_list))
|
||||
continue ;
|
||||
if (!valid_command_separator(*token_list))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// cmd_prefix cmd_name
|
||||
int valid_command_rule2(t_token **token_list)
|
||||
{
|
||||
if (!valid_io_redirect(token_list))
|
||||
return (0);
|
||||
while (valid_io_redirect(token_list))
|
||||
continue ;
|
||||
if (!valid_token(token_list, T_WORD))
|
||||
return (0);
|
||||
if (!valid_command_separator(*token_list))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// cmd_name cmd_suffix
|
||||
int valid_command_rule3(t_token **token_list)
|
||||
{
|
||||
if (!valid_token(token_list, T_WORD))
|
||||
return (0);
|
||||
if (!valid_token(token_list, T_WORD) && !valid_io_redirect(token_list))
|
||||
return (0);
|
||||
while (valid_token(token_list, T_WORD) || valid_io_redirect(token_list))
|
||||
continue ;
|
||||
if (!valid_command_separator(*token_list))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// cmd_name
|
||||
int valid_command_rule4(t_token **token_list)
|
||||
{
|
||||
if (!valid_token(token_list, T_WORD))
|
||||
return (0);
|
||||
if (!valid_command_separator(*token_list))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// cmd_prefix
|
||||
int valid_command_rule5(t_token **token_list)
|
||||
{
|
||||
if (!valid_io_redirect(token_list))
|
||||
return (0);
|
||||
while (valid_io_redirect(token_list))
|
||||
continue ;
|
||||
if (!valid_command_separator(*token_list))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
42
srcs/parsing/valid_syntax/valid_command.c
Normal file
42
srcs/parsing/valid_syntax/valid_command.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* valid_command.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 20:19:08 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int valid_command_rule1(t_token **token_list);
|
||||
int valid_command_rule2(t_token **token_list);
|
||||
int valid_command_rule3(t_token **token_list);
|
||||
int valid_command_rule4(t_token **token_list);
|
||||
int valid_command_rule5(t_token **token_list);
|
||||
|
||||
int valid_command(t_token **token_list)
|
||||
{
|
||||
t_token *cmd_start;
|
||||
|
||||
cmd_start = *token_list;
|
||||
if (valid_command_rule1(token_list))
|
||||
return (1);
|
||||
*token_list = cmd_start;
|
||||
if (valid_command_rule2(token_list))
|
||||
return (1);
|
||||
*token_list = cmd_start;
|
||||
if (valid_command_rule3(token_list))
|
||||
return (1);
|
||||
*token_list = cmd_start;
|
||||
if (valid_command_rule4(token_list))
|
||||
return (1);
|
||||
*token_list = cmd_start;
|
||||
if (valid_command_rule5(token_list))
|
||||
return (1);
|
||||
*token_list = cmd_start;
|
||||
return (0);
|
||||
}
|
||||
44
srcs/parsing/valid_syntax/valid_io_redirect.c
Normal file
44
srcs/parsing/valid_syntax/valid_io_redirect.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* valid_io_redirect.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 18:52:42 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/24 19:21:35 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static int valid_io_file(t_token **token_list);
|
||||
static int valid_io_here(t_token **token_list);
|
||||
|
||||
int valid_io_redirect(t_token **token_list)
|
||||
{
|
||||
if (valid_io_file(token_list) || valid_io_here(token_list))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int valid_io_file(t_token **token_list)
|
||||
{
|
||||
if (valid_token(token_list, '<') || valid_token(token_list, '>')
|
||||
|| valid_token(token_list, T_DGREAT))
|
||||
{
|
||||
if (valid_token(token_list, T_WORD))
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int valid_io_here(t_token **token_list)
|
||||
{
|
||||
if (valid_token(token_list, T_DLESS))
|
||||
{
|
||||
if (valid_token(token_list, T_WORD))
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
28
srcs/parsing/valid_syntax/valid_pipeline.c
Normal file
28
srcs/parsing/valid_syntax/valid_pipeline.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* valid_pipeline.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 18:51:35 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/24 19:35:16 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int valid_command(t_token **token_list);
|
||||
|
||||
int valid_pipeline(t_token **token_list)
|
||||
{
|
||||
while (valid_command(token_list))
|
||||
{
|
||||
if (*token_list == NULL)
|
||||
return (1);
|
||||
else if ((*token_list)->id != '|' || (*token_list)->next == NULL)
|
||||
return (0);
|
||||
valid_token(token_list, '|');
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
45
srcs/parsing/valid_syntax/valid_syntax.c
Normal file
45
srcs/parsing/valid_syntax/valid_syntax.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* valid_syntax.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 13:01:10 by lperrey #+# #+# */
|
||||
/* Updated: 2021/10/24 19:40:23 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int valid_pipeline(t_token **token_list);
|
||||
|
||||
int valid_syntax(t_token *token_list)
|
||||
{
|
||||
if (valid_pipeline(&token_list))
|
||||
return (1);
|
||||
else
|
||||
{
|
||||
ft_putstr_fd("minishell: syntax error near unexpected token \'", 2);
|
||||
ft_putstr_fd(token_list->content, 2);
|
||||
ft_putstr_fd("\'\n", 2);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int valid_token(t_token **token_list, enum e_token_id token_id)
|
||||
{
|
||||
if (*token_list != NULL && (*token_list)->id == token_id)
|
||||
{
|
||||
*token_list = (*token_list)->next;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int valid_command_separator(const t_token *token_list)
|
||||
{
|
||||
if (token_list == NULL || token_list->id == '|')
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#include "minishell.h"
|
||||
|
||||
int size_tab(char **split)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (*split++)
|
||||
i++;
|
||||
return (i);
|
||||
}
|
||||
|
||||
void print_tab(char **array)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (array[i])
|
||||
{
|
||||
printf("%i: [%s]\n", i, array[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_execution(char *cmd, t_all *c)
|
||||
{
|
||||
const char *filename;
|
||||
char **argv;
|
||||
char **envp;
|
||||
|
||||
// (void)cmd;
|
||||
filename = ft_strtrim(cmd, " ");
|
||||
printf("[%s]\n", filename);
|
||||
// filename = "/bin/ls";
|
||||
argv = ft_split(filename, ' ');
|
||||
envp = c->envp;
|
||||
execve(filename, argv, envp);
|
||||
}
|
||||
|
||||
void pipes_hugo(char *input, t_all *c)
|
||||
{
|
||||
char **split;
|
||||
int nbr_pipes;
|
||||
int i;
|
||||
|
||||
split = ft_split(input, '|');
|
||||
split[0] += 5; // pour sauter la premiere entree qui est "pipe"
|
||||
nbr_pipes = size_tab(split);
|
||||
//printf("%i\n", nbr_pipes);
|
||||
//print_tab(split);
|
||||
i = 0;
|
||||
cmd_execution(split[i], c);
|
||||
}
|
||||
60
srcs/shell_loop.c
Normal file
60
srcs/shell_loop.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* shell_loop.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 13:56:38 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static char *read_input(char *prompt, t_all *c);
|
||||
|
||||
void shell_loop(t_all *c)
|
||||
{
|
||||
char *line_input;
|
||||
|
||||
line_input = NULL;
|
||||
while (1)
|
||||
{
|
||||
free(line_input);
|
||||
line_input = read_input(c->prompt, c);
|
||||
if (line_input && *line_input)
|
||||
{
|
||||
add_history(line_input);
|
||||
c->token_list = lexing(line_input);
|
||||
ft_free_null(&line_input);
|
||||
if (!c->token_list)
|
||||
continue ;
|
||||
c->pipeline = parsing(c->token_list, 0);
|
||||
ft_lstclear((t_list **)&c->token_list, free);
|
||||
if (!c->pipeline)
|
||||
continue ;
|
||||
exec_cmd_line(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *read_input(char *prompt, t_all *c)
|
||||
{
|
||||
char *line_input;
|
||||
struct sigaction signal_behaviour;
|
||||
|
||||
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
|
||||
signal_behaviour.sa_handler = sigint_handler_interactive;
|
||||
sigaction(SIGINT, &signal_behaviour, NULL);
|
||||
rl_event_hook = NULL;
|
||||
line_input = readline(prompt);
|
||||
signal_behaviour.sa_handler = SIG_IGN;
|
||||
sigaction(SIGINT, &signal_behaviour, NULL);
|
||||
if (!line_input)
|
||||
{
|
||||
write(STDERR_FILENO, "exit\n", 5);
|
||||
exit_free(c, get_last_exit_status());
|
||||
}
|
||||
return (line_input);
|
||||
}
|
||||
75
srcs/shell_script.c
Normal file
75
srcs/shell_script.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* shell_script.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/26 23:47:44 by lperrey #+# #+# */
|
||||
/* Updated: 2021/12/22 14:01:52 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
static char *read_input_script(t_all *c, int script_fd);
|
||||
static void exit_signal(t_all *c);
|
||||
|
||||
void shell_script(t_all *c, int script_fd)
|
||||
{
|
||||
char *line_input;
|
||||
|
||||
line_input = NULL;
|
||||
while (1)
|
||||
{
|
||||
free(line_input);
|
||||
line_input = read_input_script(c, script_fd);
|
||||
if (!line_input)
|
||||
break ;
|
||||
if (line_input && *line_input)
|
||||
{
|
||||
c->token_list = lexing(line_input);
|
||||
ft_free_null(&line_input);
|
||||
if (!c->token_list)
|
||||
break ;
|
||||
c->pipeline = parsing(c->token_list, script_fd);
|
||||
ft_lstclear((t_list **)&c->token_list, free);
|
||||
if (!c->pipeline)
|
||||
break ;
|
||||
exec_cmd_line(c);
|
||||
if (get_last_exit_status() > EXIT_SIGNAL)
|
||||
exit_signal(c);
|
||||
}
|
||||
}
|
||||
exit_free(c, get_last_exit_status());
|
||||
}
|
||||
|
||||
static char *read_input_script(t_all *c, int script_fd)
|
||||
{
|
||||
char *line_input;
|
||||
struct sigaction signal_behaviour;
|
||||
int ret;
|
||||
|
||||
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
|
||||
signal_behaviour.sa_handler = SIG_IGN;
|
||||
sigaction(SIGINT, &signal_behaviour, NULL);
|
||||
line_input = NULL;
|
||||
ret = gnl(script_fd, &line_input, 0);
|
||||
if (ret == -1)
|
||||
{
|
||||
free(line_input);
|
||||
return (NULL);
|
||||
}
|
||||
if (!line_input[0] && ret == 0)
|
||||
{
|
||||
free(line_input);
|
||||
exit_free(c, get_last_exit_status());
|
||||
}
|
||||
return (line_input);
|
||||
}
|
||||
|
||||
static void exit_signal(t_all *c)
|
||||
{
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
exit_free(c, get_last_exit_status());
|
||||
}
|
||||
17
tests/env_var_test.c
Normal file
17
tests/env_var_test.c
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("argc = %i\n", argc);
|
||||
i = 0;
|
||||
while (argv[i])
|
||||
{
|
||||
printf("%s = |%s|\n", argv[i], getenv(argv[i]));
|
||||
i++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
17
tests/test_segfault.c
Normal file
17
tests/test_segfault.c
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
# include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
int i;
|
||||
char *str;
|
||||
|
||||
str = NULL;
|
||||
i = 0;
|
||||
while (str[i])
|
||||
{
|
||||
write(1, &str[i], 1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
7
tests/trop_de_pipes.sh
Normal file
7
tests/trop_de_pipes.sh
Normal file
File diff suppressed because one or more lines are too long
@@ -4,3 +4,10 @@
|
||||
...
|
||||
fun:readline
|
||||
}
|
||||
|
||||
{
|
||||
<readline history>
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:add_history
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user