12 Commits

74 changed files with 854 additions and 3375 deletions

7
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.DS_Store .DS_Store
Thumbs.db
*.o *.o
*.swp *.swp
*.out *.out
@@ -10,11 +9,7 @@ Thumbs.db
*.dSYM *.dSYM
.vscode .vscode
*.lnk *.lnk
*.zip
memo memo
memo.txt memo.txt
minishell minishell
arg_test *.zip
osef_temp
env_var_test
memo_local

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "libft"] [submodule "libft"]
path = libft path = libft
url = git@bitbucket.org:LuckyLaszlo/libft.git url = git@bitbucket.org:LuckyLaszlo/libft.git
[submodule "minishell_tests"]
path = minishell_tests
url = git@bitbucket.org:LuckyLaszlo/minishell_tests.git

View File

@@ -2,18 +2,10 @@ NAME = minishell
CC = clang CC = clang
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) # add -g CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -g
VPATH = $(DIR_SRCS) VPATH = $(DIR_SRCS)
DIR_SRCS = srcs \ DIR_SRCS = srcs srcs/builtins
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) INCLUDES = -I$(HEADERS_D) -I$(LIBFT_D)
@@ -29,25 +21,10 @@ LIBS = -L $(LIBFT_D) -lft \
LIBFT_D = ./libft LIBFT_D = ./libft
LIBFT = $(LIBFT_D)/libft.a LIBFT = $(LIBFT_D)/libft.a
SRCS = main.c \ SRCS = main.c init.c free.c generic.c \
shell_loop.c shell_script.c \ env.c exit.c \
init.c init_prompt.c init_readline.c init_shlvl.c open_script_file.c \ pipes_hugo.c \
retrieve_path.c \ parser_hugo.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 DIR_OBJS = builds
OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o) OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o)

518
README.md Normal file
View File

@@ -0,0 +1,518 @@
## 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 Normal file
View File

@@ -0,0 +1,12 @@
builds
echo
headers
libft
Makefile
minishell
minishell.en.subject.pdf
README.md
ressources
srcs
tests
valgrind_readline.supp

14
file.txt Normal file
View File

@@ -0,0 +1,14 @@
builds
echo
file.txt
headers
libft
Makefile
minishell
minishell.en.subject.pdf
README.md
ressources
srcs
tests
test.txt
valgrind_readline.supp

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/03 19:14:46 by lperrey #+# #+# */ /* Created: 2021/10/03 19:14:46 by lperrey #+# #+# */
/* Updated: 2021/11/27 09:09:31 by lperrey ### ########.fr */ /* Updated: 2021/10/13 16:09:32 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,7 +15,6 @@
# include "libft.h" # include "libft.h"
# include <fcntl.h> # include <fcntl.h>
# include <unistd.h> # include <unistd.h>
# include <sys/ioctl.h>
# include <stdlib.h> # include <stdlib.h>
# include <string.h> # include <string.h>
# include <errno.h> # include <errno.h>
@@ -27,19 +26,15 @@
# include <signal.h> # include <signal.h>
# include <dirent.h> # include <dirent.h>
# include <termios.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 <term.h>
// sudo apt install libreadline-dev # include <stdio.h>
# include <readline/readline.h> # include <readline/readline.h> // sudo apt install libreadline-dev
# include <readline/history.h> # include <readline/history.h>
# include <stdio.h>
# include "minishell_macro.h"
# include "minishell_structs.h" # include "minishell_structs.h"
# include "minishell_macro.h"
# include "minishell_term_colors.h" # include "minishell_term_colors.h"
# include "minishell_user_macro.h" # include "minishell_user_macro.h"
# include "minishell_prototypes.h" # include "minishell_prototypes.h"
@@ -57,8 +52,8 @@
** <fcntl.h>: open() ** <fcntl.h>: open()
** <unistd.h>: read(), write(), close(), fork(), getcwd(), chdir(), ** <unistd.h>: read(), write(), close(), fork(), getcwd(), chdir(),
** stat(), lstat(), fstat(), execve(), dup(), dup2(), pipe(), ** stat(), lstat(), fstat(), execve(), dup(), dup2(), pipe(),
** isatty(), ttyname(), ttyslot(), tcsetattr(), tcgetattr() ** isatty(), ttyname(), ttyslot(), ioctl(),
** <sys/ioctl.h>: ioctl() ** tcsetattr(), tcgetattr()
** <stdlib.h>: malloc(), free(), exit(), getenv() ** <stdlib.h>: malloc(), free(), exit(), getenv()
** <string.h>: strerror(), define NULL, define size_t ** <string.h>: strerror(), define NULL, define size_t
** <errno.h>: define errno ** <errno.h>: define errno

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:35:55 by lperrey #+# #+# */ /* Created: 2021/10/08 02:35:55 by lperrey #+# #+# */
/* Updated: 2021/11/27 10:43:43 by lperrey ### ########.fr */ /* Updated: 2021/10/08 03:01:43 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -18,37 +18,4 @@
# define PROMPT_CHEVRON "> " # define PROMPT_CHEVRON "> "
# define PROMPT_EURO "\001€\002 \001\b\002" # 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 #endif

View File

@@ -6,99 +6,33 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */ /* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:28:07 by lperrey ### ########.fr */ /* Updated: 2021/10/19 23:41:25 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef MINISHELL_PROTOTYPES_H #ifndef MINISHELL_PROTOTYPES_H
# define MINISHELL_PROTOTYPES_H # define MINISHELL_PROTOTYPES_H
extern int g_switch_heredoc_sigint;
extern char **environ;
// Init // Init
int init(t_all *c, char *argv[]); int init(t_all *c, char *envp[]);
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 // Builtins
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_env(int argc, char *argv[], t_all *c);
int builtin_echo(int argc, char *argv[], t_all *c); int builtin_exit(int argc, char *argv[], t_all *c);
// Free // Free
int exit_free(t_all *c, int exit_status); int free_exit(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 // Generic
char *ft_strjoinfree(char *s1, char *s2); char *ft_strjoinfree(char *s1, char *s2);
char *ft_strjoinfree_s1(char *s1, const char *s2); char *ft_strjoinfree_s1(char *s1, const char *s2);
char *ft_strjoinfree_s2(const char *s1, 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);
char **ft_split_quotes(char const *s, char c); // pipes hugo
char *ft_strdup_quotes(const char *s); void pipes_hugo(char *input, t_all *c);
// parser hugo
// Signals handler void **cmd_path(char **argv, char **envp);
void sigint_handler_interactive(int signum); int handle_fd(char **input, int i, int fdin, t_cmd *cmd);
void sigint_handler_heredoc(int signum); t_list *parser(char *input, char **envp);
// last_exit_status
int set_last_exit_status(int new_value);
int get_last_exit_status(void);
#endif #endif

View File

@@ -6,43 +6,30 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */ /* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:13:45 by lperrey ### ########.fr */ /* Updated: 2021/10/20 09:11:41 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef MINISHELL_STRUCTS_H #ifndef MINISHELL_STRUCTS_H
# define MINISHELL_STRUCTS_H # define MINISHELL_STRUCTS_H
struct s_all; typedef struct s_all
typedef struct s_token
{ {
char *content; char **envp;
struct s_token *next; char *prompt_base;
enum e_token_id id; char *prompt;
} t_token; } t_all;
typedef int (*t_builtin_f)(int,char **,struct s_all *);
typedef struct s_cmd typedef struct s_cmd
{ {
char **argv; char **argv;
char *path; pid_t pid;
t_builtin_f builtin_f; void *builtin;
int fd_in; int pipe_in;
int fd_out; int pipe_out;
pid_t pid; int fd_redirect;
int error; int fd_in;
int fd_out;
} t_cmd; } 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 #endif

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 03:36:37 by lperrey #+# #+# */ /* Created: 2021/10/10 03:36:37 by lperrey #+# #+# */
/* Updated: 2021/10/19 20:30:34 by lperrey ### ########.fr */ /* Updated: 2021/10/10 20:58:28 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,7 +15,7 @@
# include "minishell_macro.h" # include "minishell_macro.h"
# define U_PROMPT_END PROMPT_CHEVRON # define U_PROMPT_END PROMPT_EURO
# define U_DEFAULT_USER "NoUser" # define U_DEFAULT_USER "NoUser"
# define U_DEFAULT_NAME "NoName" # define U_DEFAULT_NAME "NoName"

2
libft

Submodule libft updated: af88c1ce23...1401fddfcd

1
ressources/parsing.md Normal file
View File

@@ -0,0 +1 @@
https://raw.githubusercontent.com/kukinpower/minishell/master/images/3.png

BIN
ressources/parsing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

View File

@@ -1,82 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,47 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -6,17 +6,16 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 05:01:26 by lperrey #+# #+# */ /* Created: 2021/10/10 05:01:26 by lperrey #+# #+# */
/* Updated: 2021/12/01 17:19:48 by lperrey ### ########.fr */ /* Updated: 2021/10/10 07:37:29 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int builtin_env(int argc, char *argv[], t_all *c) int builtin_env(int argc, char *argv[], t_all *c) // WIP
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
(void)c; ft_putendl_arr_fd(c->envp, 1);
ft_putendl_arr_fd(environ, 1);
return (0); return (0);
} }

View File

@@ -6,18 +6,18 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 05:01:22 by lperrey #+# #+# */ /* Created: 2021/10/10 05:01:22 by lperrey #+# #+# */
/* Updated: 2021/11/29 12:43:47 by lperrey ### ########.fr */ /* Updated: 2021/10/11 01:50:53 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int builtin_exit(int argc, char *argv[], t_all *c) int builtin_exit(int argc, char *argv[], t_all *c) // WIP
{ {
unsigned char status; unsigned char status;
int i; int i;
status = get_last_exit_status(); status = 0;
if (argc > 2) if (argc > 2)
return (ft_reti_print(1, "exit: too many arguments\n", 2)); return (ft_reti_print(1, "exit: too many arguments\n", 2));
if (argc == 2) if (argc == 2)
@@ -36,7 +36,7 @@ int builtin_exit(int argc, char *argv[], t_all *c)
return (ft_reti_print(2, " numeric argument required\n", 2)); return (ft_reti_print(2, " numeric argument required\n", 2));
} }
} }
status = ft_atoi(argv[1]); status = ft_atoi(argv[1]);
} }
return (exit_free(c, status)); return (free_exit(c, status));
} }

View File

@@ -1,96 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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
*/

View File

@@ -1,29 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,61 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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
*/

View File

@@ -1,29 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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
*/

View File

@@ -1,111 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,111 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,63 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,55 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,65 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,19 +1,20 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* ft_free_null.c :+: :+: :+: */ /* free.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */ /* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
/* Updated: 2021/12/16 03:59:21 by lperrey ### ########.fr */ /* Updated: 2021/10/10 23:59:25 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
void ft_free_null(void *ptr) int free_exit(t_all *c, int exit_status)
{ {
free(*(char **)ptr); free(c->prompt_base);
*(char **)ptr = NULL; free(c->prompt);
exit(exit_status);
} }

View File

@@ -1,12 +1,12 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* ft_strjoinfree.c :+: :+: :+: */ /* generic.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */ /* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/16 03:39:09 by lperrey ### ########.fr */ /* Updated: 2021/10/08 09:28:49 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

@@ -1,67 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,70 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,31 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,37 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,56 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,179 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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(&quote_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(&quote_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(&quote_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(&quote_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);
}

View File

@@ -1,64 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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(&quote_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);
}

View File

@@ -1,30 +1,30 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* init_prompt.c :+: :+: :+: */ /* init.c :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */ /* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:25:46 by lperrey ### ########.fr */ /* Updated: 2021/10/10 21:56:33 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
static char *init_prompt_base(void); static char *init_prompt_base(void);
static char *init_prompt(char *prompt_base);
int init_prompt(t_all *c, int script_fd) int init(t_all *c, char *envp[])
{ {
if (!script_fd && isatty(STDIN_FILENO)) ft_bzero(c, sizeof *c);
{ c->envp = envp;
c->prompt_base = init_prompt_base(); c->prompt_base = init_prompt_base();
if (!c->prompt_base) if (!c->prompt_base)
return (0); return (ft_reti_perror(0, "init_prompt_base() fail"));
c->prompt = update_prompt(c->prompt_base); c->prompt = init_prompt(c->prompt_base);
if (!c->prompt) if (!c->prompt)
return (0); return (ft_reti_perror(0, "init_prompt() fail"));
}
return (1); return (1);
} }
@@ -39,32 +39,20 @@ static char *init_prompt_base(void)
if (!tmp) if (!tmp)
tmp = U_DEFAULT_USER; tmp = U_DEFAULT_USER;
prompt_base = ft_strjoin(TERM_LIGHT_GREEN, tmp); prompt_base = ft_strjoin(TERM_LIGHT_GREEN, tmp);
if (!prompt_base)
return (NULL);
prompt_base = ft_strjoinfree_s1(prompt_base, "@"); prompt_base = ft_strjoinfree_s1(prompt_base, "@");
if (!prompt_base)
return (NULL);
tmp = getenv("NAME"); tmp = getenv("NAME");
if (!tmp) if (!tmp)
tmp = U_DEFAULT_NAME; tmp = U_DEFAULT_NAME;
prompt_base = ft_strjoinfree_s1(prompt_base, tmp); 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); prompt_base = ft_strjoinfree_s1(prompt_base, TERM_RESET":"TERM_LIGHT_BLUE);
if (!prompt_base)
return (NULL);
return (prompt_base); return (prompt_base);
} }
char *update_prompt(char *prompt_base) static char *init_prompt(char *prompt_base)
{ {
char *prompt; char *prompt;
prompt = ft_strjoinfree_s2(prompt_base, getcwd(NULL, 0)); prompt = ft_strjoinfree_s2(prompt_base, getcwd(NULL, 0));
if (!prompt)
return (NULL);
prompt = ft_strjoinfree_s1(prompt, TERM_RESET U_PROMPT_END); prompt = ft_strjoinfree_s1(prompt, TERM_RESET U_PROMPT_END);
if (!prompt)
return (NULL);
return (prompt); return (prompt);
} }

View File

@@ -1,35 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,33 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,37 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,26 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}
}
}

View File

@@ -1,65 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,63 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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(&quotes_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);
}

View File

@@ -1,69 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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
*/

View File

@@ -1,31 +1,113 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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" #include "minishell.h"
int g_switch_heredoc_sigint; 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 main(int argc, char *argv[]) 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[])
{ {
t_all c; t_all c;
(void)argc; (void)argc;
if (!init(&c, argv)) (void)argv;
exit_free(&c, EXIT_FAILURE); if (!init(&c, envp))
if (c.script_fd) exit(EXIT_FAILURE);
shell_script(&c, c.script_fd); shell_loop(&c);
else if (!isatty(STDIN_FILENO))
shell_script(&c, STDIN_FILENO);
else
shell_loop(&c);
return (0); return (0);
} }

View File

@@ -1,52 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,98 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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()");
}

View File

@@ -1,27 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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));
}

View File

@@ -1,35 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,39 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

81
srcs/parser_hugo.c Normal file
View File

@@ -0,0 +1,81 @@
#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);
}

View File

@@ -1,95 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,52 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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;
}
}

View File

@@ -1,82 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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
*/

View File

@@ -1,43 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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, &quotes_state);
expand = expand->next;
if (!expand)
{
perror("expand_token() error");
return (ft_lstclear(&head.next, free));
}
}
return (head.next);
}

View File

@@ -1,82 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,59 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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;
}

View File

@@ -1,34 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,115 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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
;
*/

View File

@@ -1,165 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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.
*/

View File

@@ -1,138 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,83 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,42 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,44 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,28 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,45 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

53
srcs/pipes_hugo.c Normal file
View File

@@ -0,0 +1,53 @@
#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);
}

View File

@@ -1,60 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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);
}

View File

@@ -1,75 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 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());
}

0
test.txt Normal file
View File

View File

@@ -1,17 +0,0 @@
# 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);
}

View File

@@ -1,17 +0,0 @@
# 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);
}

File diff suppressed because one or more lines are too long

View File

@@ -4,10 +4,3 @@
... ...
fun:readline fun:readline
} }
{
<readline history>
Memcheck:Leak
...
fun:add_history
}