138 Commits

Author SHA1 Message Date
Hugo LAMY
0ac5efeaed delete tester 2022-03-15 13:58:32 +01:00
lperrey
19c3d51726 norme 2021-12-22 22:19:14 +01:00
lperrey
dfe3f6977a SIGPIPE ignore in builtins commands 2021-12-22 21:54:22 +01:00
lperrey
fd72d63dd6 fixed invalids rules in rules_command.c 2021-12-22 20:26:51 +01:00
lperrey
69adb1cf2f retrieve_path() leak fixed 2021-12-22 19:34:21 +01:00
lperrey
9bffb99b30 fix invalid read size in ft_getenv_position() 2021-12-22 18:11:33 +01:00
lperrey
9e8d92e0b5 norme 2021-12-22 17:27:15 +01:00
lperrey
523f560eab here_doc script_fd fix
+ line_len in here_doc
+ error message SIGQUIT
2021-12-22 15:57:02 +01:00
LuckyLaszlo
b51535cdbc export builtin bugfix
now check frst char before split
return error even if argument first char is '='
2021-12-21 22:42:01 +01:00
LuckyLaszlo
638dbbaf9c pipeline.c refactoring 2021-12-21 17:34:44 +01:00
LuckyLaszlo
54c9df31e4 error message on cmd segfault. 2021-12-21 17:33:23 +01:00
lperrey
5a39470290 fixed close() of c->script_fd 2021-12-21 12:22:25 +01:00
lperrey
e4c4589d3c fixed quotes handling in expand token
+ split expand_token.c in multiples files
2021-12-21 01:22:38 +01:00
lperrey
80917cae7c fixed mistake in rules_command.c 2021-12-21 00:01:51 +01:00
lperrey
8ed97346f7 fixed argv open().
previously wrongly dup2() to STDIN.
2021-12-20 22:52:41 +01:00
lperrey
6a9b7bae1b rules_command.c refactoring for clarity 2021-12-20 21:32:17 +01:00
lperrey
e138e6550b close cmd fd after each exec 2021-12-20 18:10:53 +01:00
lperrey
0cfb13595c merge 2021-12-20 17:58:24 +01:00
lperrey
11d2f36307 norme headers
+ add -Werror flag in Makefile
2021-12-20 17:56:35 +01:00
Hugo LAMY
b8281e329c remis Werror dans makefile et resoud warning dans new_token_for_each_field pour le retour de lst_clear 2021-12-20 17:25:36 +01:00
Hugo LAMY
7de89b43b1 srcs a la norme 2021-12-20 17:02:57 +01:00
Hugo LAMY
8959166804 norme en cours... 2021-12-20 15:54:07 +01:00
Hugo LAMY
0a64977cdc merging conflicts 2021-12-20 15:07:58 +01:00
Hugo LAMY
59a43ea1cc momentanee solution pour extern variable 2021-12-20 15:06:31 +01:00
LuckyLaszlo
49099a0abd shell _script() use gnl() instead of readline()
to prevent copy of input to terminal.
+ here_doc_write_script()  for nontty STDIN
2021-12-18 15:25:45 +01:00
LuckyLaszlo
0e520ef31e fixed crash in builtin export with "" argument
+ builtin unset now update PATH
2021-12-18 13:45:20 +01:00
LuckyLaszlo
fa474c86ab fixed signal exit in shell_script() 2021-12-18 08:55:54 +01:00
LuckyLaszlo
afbb1cd2e0 shell_script()
+ reset "rl_event_hook" to NULL after here_doc()
+ split init.c in multiple files
+ submodule minishell_tests
2021-12-18 05:42:08 +01:00
LuckyLaszlo
fa71189132 split valid_command.c in two files 2021-12-17 04:13:21 +01:00
LuckyLaszlo
36de7bf150 added valid_command() rule (only "cmd_prefix")
+ skip exec if no cmd_name in a command
2021-12-17 03:17:58 +01:00
LuckyLaszlo
59f0b7603b deleted terminal.c 2021-12-16 06:39:29 +01:00
LuckyLaszlo
e5852579ef submodule minishell_tests 2021-12-16 06:15:26 +01:00
LuckyLaszlo
81cc6fbff6 handle_access_error() exit status 2021-12-16 06:04:03 +01:00
LuckyLaszlo
06f1987ae4 small adjust in files 2021-12-16 05:05:25 +01:00
LuckyLaszlo
20c71bccbb generic.c file split 2021-12-16 04:01:29 +01:00
LuckyLaszlo
f53969cd45 srcs files moved 2021-12-16 03:37:34 +01:00
LuckyLaszlo
5a0a237aaa expansions refactoring done 2021-12-16 03:12:32 +01:00
LuckyLaszlo
e5f033694b expansions refactoring WIP 2021-12-15 13:42:41 +01:00
LuckyLaszlo
5c1d8f527c bugfix, pipeline must continue if expand_redirection() fail
+ ft_perror_io() delete
2021-12-11 21:22:43 +01:00
LuckyLaszlo
9c660d4f92 expand_redirection() : rejoin token list on error
+ words_expansions.c -> expansions.c
+ generic.c misc
2021-12-11 20:19:26 +01:00
LuckyLaszlo
a7de843dc1 check of cmd->error :
- before calling cmd_find_access()
- before calling simple_command_builtin()
2021-12-11 05:53:55 +01:00
LuckyLaszlo
465c4de21e update submodule commit 2021-12-11 04:58:14 +01:00
LuckyLaszlo
82f0362323 expand redirections 2021-12-11 04:28:43 +01:00
LuckyLaszlo
d3d55386d9 refactoring parsing (wip) 2021-12-11 04:27:57 +01:00
LuckyLaszlo
9322ec9ec9 close_stdio() at exit 2021-12-10 06:34:44 +01:00
LuckyLaszlo
592bcb4e93 bugfix pipeline redirections 2021-12-09 20:57:31 +01:00
LuckyLaszlo
f7d37fadb6 here_doc bugfix 2021-12-09 05:32:20 +01:00
LuckyLaszlo
73feaf0230 builtin cd 2021-12-09 04:19:27 +01:00
LuckyLaszlo
34da9678dc shlvl_init() fixed leak 2021-12-08 22:00:18 +01:00
LuckyLaszlo
322d8d5f09 added minishell_tests as submodule 2021-12-08 21:10:03 +01:00
LuckyLaszlo
cee6a8962b shlvl_init(), set SHLVL
+ export builtin small change
2021-12-08 06:36:52 +01:00
LuckyLaszlo
bcc82aabaf signals adjustements 2021-12-08 04:45:12 +01:00
LuckyLaszlo
8125e43065 init_prompt() correct error return 2021-12-08 04:02:00 +01:00
LuckyLaszlo
312c90539b adjustement to ft_strjoin() after libft update
from libft : ft_strjoin() no longer return if an arg is NULL
2021-12-08 03:46:40 +01:00
LuckyLaszlo
8a7611da92 fixed empty quotes expansions 2021-12-08 03:03:16 +01:00
LuckyLaszlo
caa733e14a open_pipes() bugfix
+ write "exit" to STDERR (like bash)
+ set_last_exit_status() on CTRL-C
2021-12-08 00:22:06 +01:00
LuckyLaszlo
200e043a8c builtin export fixed and refactored
+ builtin exit, env verif OK
2021-12-06 03:56:05 +01:00
LuckyLaszlo
2d85c34b98 commented debug print in parsing 2021-12-06 01:14:18 +01:00
LuckyLaszlo
b7b3cec6e0 builtin unset + fixed builtin export 2021-12-05 18:15:23 +01:00
LuckyLaszlo
66183ab441 cd refactoring, error_wrappers 2021-12-05 16:28:41 +01:00
LuckyLaszlo
c3a9035622 builtins cd, pwd (todo, refactoring cd) 2021-12-05 01:01:27 +01:00
LuckyLaszlo
27c00a78a0 export builtin 2021-12-04 18:14:24 +01:00
LuckyLaszlo
2eed0f2d45 little fix, ft_lstnew_generic() prototype.
+ unused c var in builtin_env()
2021-12-03 16:10:04 +01:00
LuckyLaszlo
fb1974dd3b redirect readline() prompt to stderr (like bash)
useful for testing program.
2021-12-02 01:47:14 +01:00
LuckyLaszlo
d710f5ef68 fixed readline() leak/double_free with **environ 2021-12-02 01:35:02 +01:00
LuckyLaszlo
b3f74c4179 refactoring exec 2021-12-01 17:24:32 +01:00
LuckyLaszlo
b08da252de lexing comment remove 2021-12-01 16:02:25 +01:00
LuckyLaszlo
025ef76c01 refactoring lexing 2021-12-01 16:00:36 +01:00
LuckyLaszlo
ffd06c4b95 ft_free_null()
+ refactoring shell_loop()
2021-11-30 14:12:05 +01:00
LuckyLaszlo
b265e8475a free_exit() renamed exit_free() 2021-11-29 12:44:46 +01:00
LuckyLaszlo
33f4878f36 exit status Macro 2021-11-29 12:42:52 +01:00
LuckyLaszlo
cb5c2dcb30 "cmd_arr/cmd_array" renamed to "pipeline" 2021-11-29 12:32:03 +01:00
LuckyLaszlo
aa7efdab15 delete useless files 2021-11-29 12:15:45 +01:00
LuckyLaszlo
5b3e566b25 searching solution for invalid free in readline. 2021-11-29 12:15:17 +01:00
LuckyLaszlo
3baf91afb3 replaced occurrences of last exit_status
+ deleted envp comments
+ WIP Macro exit status
+ TODO : Invalid free of environ in readline
2021-11-27 12:59:16 +01:00
LuckyLaszlo
843b6d84c5 "extern char **environ" in header file
+ global var g_all deleted, renamed switch_heredoc_sigint
2021-11-26 21:58:52 +01:00
LuckyLaszlo
07e98c7cf8 "e_quotes_state" redefined in minishell_structs.h 2021-11-26 21:31:17 +01:00
LuckyLaszlo
b9d7ebb3cb fix last_exit_status.c 2021-11-26 20:51:07 +01:00
LuckyLaszlo
18d430c5cb CO-CODE Hugo-Luke
+ last_exit_status set/get functions for here_doc
+ TODO : replace all occurences of last_exit_status
+ **environ fix
+ builtin_unset() fix
2021-11-26 20:44:29 +01:00
hugogogo
3465354af5 cd ok et appel a path dans export 2021-11-26 00:00:00 +01:00
hugogogo
32eab95d48 qq recherches sur le signal et heredoc 2021-11-25 22:44:35 +01:00
hugogogo
ac11eee947 unset ok 2021-11-25 21:33:46 +01:00
hugogogo
ef3e91be13 variable extern environ fonction avec getenv et export ok 2021-11-25 19:45:41 +01:00
hugogogo
80410e6d81 gestion sigint dans heredoc fonctionne basiquement 2021-11-25 10:06:48 +01:00
hugogogo
ef12d6ba4b merging conflict 2021-11-18 21:33:47 +01:00
hugogogo
0b6d8cf127 debut modifs heredoc 2021-11-18 19:51:08 +01:00
hugogogo
74ee526d57 ajout un fonctionnement signaux avec heredoc 2021-11-18 17:20:19 +01:00
LuckyLaszlo
7c65dcd897 fixed signal exit status only for last command 2021-11-18 14:38:23 +01:00
LuckyLaszlo
0bd9dcb3bb simple_cmd_builtin() done.
+ exec_cmd_line.c split in multiples files
2021-11-18 14:28:56 +01:00
hugogogo
c11c61ec5e en cours de gestion des signaux dans heredoc 2021-11-18 13:29:57 +01:00
LuckyLaszlo
91d5a0d14c pipeline_exec() complete
+ TODO : simple_cmd_builtin()
+ libft small update
2021-11-18 12:38:27 +01:00
hugogogo
e715c09de1 precisions sur fonctionnement heredoc 2021-11-17 22:07:58 +01:00
hugogogo
860c4daaf0 recherche sur le fonctionnement du heredoc ecrit dans le readme 2021-11-17 21:53:25 +01:00
hugogogo
6a4b1f54b2 Merge branch 'master' of bitbucket.org:LuckyLaszlo/minishell into hugogogo 2021-11-17 15:28:09 +01:00
LuckyLaszlo
26993144cc CO-CODE Hugo-Luke
+ signals handling adjusted
+ wait_subshell() with last_exit_status
+ miscs
2021-11-17 01:35:06 +01:00
LuckyLaszlo
965cf99ca5 merge
+ readline() replace gnl() in here_doc
+ "int error" in struct "t_cmd"
2021-11-16 22:30:20 +01:00
hugogogo
493ac0bd40 libft update 2021-11-16 20:01:41 +01:00
hugogogo
f70ee4bae0 before merging with lucky 2021-11-16 19:11:15 +01:00
LuckyLaszlo
140549db00 WIP exec_cmd_line()
+ fix error handle in redirections()
+ rename ft_free_cmd_arr() to free_pipeline()
+ "char **path" added to "struct t_all"
+ misc
2021-11-16 08:49:57 +01:00
hugogogo
36766501ba gestion des signaux avec execve ok dans test 2021-11-15 21:56:50 +01:00
hugogogo
57c271b9e2 signaux fonctionnent sur test 2021-11-15 16:09:19 +01:00
LuckyLaszlo
bb77de0588 cmd_array_fill_argv() 2021-11-14 12:57:18 +01:00
LuckyLaszlo
402196b9a9 fix here_doc leak 2021-11-14 11:15:30 +01:00
LuckyLaszlo
66b48dc99d redirections WIP 2021-11-14 11:05:58 +01:00
LuckyLaszlo
1e682f796d fix invalid read with quotes functions
+ ft_free_cmd_arr()
2021-11-14 04:59:38 +01:00
LuckyLaszlo
106af37b58 words_expansions() complete
+ TODO : need refactoring and fix to valgrind invalid read size
+ redirections() WIP
+ Generic ft_dup_2d_arr(), ft_split_quotes(), ft_strdup_quotes()
+ shell_loop() continue on error
+ various small fix
2021-11-14 00:09:42 +01:00
LuckyLaszlo
86707f9fc6 libft small change 2021-11-13 23:45:10 +01:00
hugogogo
47ae67ed14 ajout des builtins pwd cd et export 2021-11-11 17:44:42 +01:00
hugogogo
d65a701186 add ctrl-c and ctrl-d aka eof handling 2021-11-10 13:46:17 +01:00
LuckyLaszlo
0ae84abb14 bugfix expansions 2021-11-08 04:02:43 +01:00
LuckyLaszlo
0a5c7545c1 WIP parsing expansions 2021-11-07 04:41:17 +01:00
hugogogo
0a33916c75 tests ok pour modifier fonctionnement de minishell 2021-11-05 16:26:27 +01:00
hugogogo
5a98927eff ajout des descriptions des functions de readline 2021-11-05 14:38:11 +01:00
hugogogo
a6959ac1f8 external functions in readme ok 2021-11-04 17:37:19 +01:00
hugogogo
03acb65880 external functions in readme ok 2021-11-04 17:36:19 +01:00
hugogogo
533128af89 still continue to fill readme with external functions 2021-11-04 15:46:31 +01:00
hugogogo
bb44760e2b continue to fill readme with external functions 2021-11-04 15:16:36 +01:00
hugogogo
f93825ee59 descriptions functions externes dans readme 2021-11-04 14:57:34 +01:00
hugogogo
07f458c875 mise a jour libft 2021-11-02 14:39:38 +01:00
hugogogo
b9fc6a9bc4 merge hugogogo with master resolve conflict 2021-11-02 14:16:32 +01:00
hugogogo
d4151227b3 merge hugogogo with master 2021-11-02 14:04:23 +01:00
hugogogo
27ac62bddc merging luke remote with origin local 2021-11-02 13:56:26 +01:00
hugogogo
a926a817da parsing et execution partielle de hugo 2021-11-02 13:38:52 +01:00
LuckyLaszlo
22d4bbfdd0 norme 2021-10-31 01:10:57 +02:00
LuckyLaszlo
c0ef57499a lexing refactoring 2021-10-30 22:47:02 +02:00
LuckyLaszlo
ab2aa509df signals and termios WIP
+ shell script placeholder
+ generics functions
+ valgrind add_history() supp
+ misc
2021-10-30 16:39:24 +02:00
hugogogo
698dcbe1ed execute ok, il manque les heredocs 2021-10-30 15:34:45 +02:00
hugogogo
118e2e5bef handle fd 2021-10-30 15:27:41 +02:00
hugogogo
0292425bc1 path of cmd ok 2021-10-30 14:43:06 +02:00
LuckyLaszlo
58ef5a4a03 Fix free for final empty token. 2021-10-30 12:44:06 +02:00
hugogogo
75987a117e cmd argv fill with word and without redirections 2021-10-30 10:20:43 +02:00
hugogogo
15bc4d2158 refonte de la gestion des cmd dans parsing 2021-10-29 13:26:38 +02:00
hugogogo
b1b8a61921 fill cmd et execute pipes ok 2021-10-28 21:00:00 +02:00
hugogogo
62955af5b8 merge conflict with master 2021-10-27 14:48:31 +02:00
LuckyLaszlo
815cedb8ca syntax analysis with simplified shell grammar
+ TODO : bug to fix in lexer.c
2021-10-24 19:58:19 +02:00
LuckyLaszlo
906074d2cb envp dup array
+ c->last_exit_status
2021-10-24 10:23:20 +02:00
LuckyLaszlo
39de10e001 echo builtin
+ WIP grammar rules in parsing.txt
+ test trop_de_pipes.sh
2021-10-22 10:53:06 +02:00
LuckyLaszlo
1054f3d6ff lexer (need refactoring)
+ littles miscs
2021-10-19 20:25:41 +02:00
74 changed files with 3375 additions and 854 deletions

7
.gitignore vendored
View File

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

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[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,10 +2,18 @@ NAME = minishell
CC = clang CC = clang
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -g CFLAGS = -Wall -Wextra -Werror $(INCLUDES) # add -g
VPATH = $(DIR_SRCS) VPATH = $(DIR_SRCS)
DIR_SRCS = srcs srcs/builtins DIR_SRCS = srcs \
srcs/init \
srcs/builtins \
srcs/lexing \
srcs/parsing srcs/parsing/valid_syntax \
srcs/parsing/expansions srcs/parsing/redirections \
srcs/exec \
srcs/generic \
srcs/misc \
INCLUDES = -I$(HEADERS_D) -I$(LIBFT_D) INCLUDES = -I$(HEADERS_D) -I$(LIBFT_D)
@@ -21,10 +29,25 @@ LIBS = -L $(LIBFT_D) -lft \
LIBFT_D = ./libft LIBFT_D = ./libft
LIBFT = $(LIBFT_D)/libft.a LIBFT = $(LIBFT_D)/libft.a
SRCS = main.c init.c free.c generic.c \ SRCS = main.c \
env.c exit.c \ shell_loop.c shell_script.c \
pipes_hugo.c \ init.c init_prompt.c init_readline.c init_shlvl.c open_script_file.c \
parser_hugo.c retrieve_path.c \
free.c \
signals.c error_wrappers.c last_exit_status.c \
lexing.c fill_token.c check_operators.c \
parsing.c create_pipeline.c \
valid_syntax.c valid_pipeline.c valid_command.c rules_command.c valid_io_redirect.c \
expansions.c \
expand_token.c content_expand.c content_copy.c \
rejoin_after_expand.c new_token_for_each_field.c \
redirections.c here_doc.c \
exec_cmd_line.c pipeline.c \
find_access.c subshell_exec.c subshell_wait.c simple_cmd_builtin.c \
cd.c pwd.c export.c unset.c exit.c env.c echo.c \
ft_split_quotes.c ft_strdup_quotes.c \
ft_strjoinfree.c ft_lst_func.c ft_isinset_str.c ft_is_posix_name.c \
ft_getenv.c ft_free_null.c ft_2d_arr_func.c \
DIR_OBJS = builds DIR_OBJS = builds
OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o) OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o)

518
README.md
View File

@@ -1,518 +0,0 @@
## sommaire :
---
- [1. todo list :](#markdown-header-1-todo-list)
- [2. parsing :](#markdown-header-2-parsing)
- [2.1. methode arbre binaire :](#markdown-header-21-methode-arbre-binaire)
- [3. gerer les quotes et la separation des arguments :](#markdown-header-3-gerer-les-quotes-et-la-separation-des-arguments)
- [3.1. tentative methode 1 :](#markdown-header-31-tentative-methode-1)
- [3.1.1. pseudo code :](#markdown-header-311-pseudo-code)
- [3.1.2. application :](#markdown-header-312-application)
- [3.1.3. erreur :](#markdown-header-313-erreur)
- [3.2. tentative methode 2 :](#markdown-header-32-tentative-methode-2)
- [3.2.1. deroulement :](#markdown-header-321-deroulement)
- [3.2.2. application :](#markdown-header-322-application)
- [3.3. comportement reel chelou :](#markdown-header-33-comportement-reel-chelou)
- [4. notes :](#markdown-header-4-notes)
## 1. todo list :
---
- **global features :**
- `prompt` *show a prompt*
- `history` **? the command history ?**
- `binaries` *fetch and launch the right executable*
- `'` `"` `;` `\` **? don't interpret special characters and unclosed quotes ?**
- **pipes :** [video vulgarisation](https://www.youtube.com/watch?v=bKzonnwoR2I)
- `|` *pipes*
- **expensions :**
- `$` *variable expension*
- `$?` *exit return of last executed process* [ressource stackoverflow](https://stackoverflow.com/questions/7248031/meaning-of-dollar-question-mark-in-shell-scripts)
- **quotes :** [ressource](https://linuxhandbook.com/quotes-in-bash/)
- `'` *(ignore any special characters)*
- `"` *(ignore any special characters except '$')*
- **redirections & heredocs :** [ressource](https://www.gnu.org/software/bash/manual/html_node/Redirections.html) / [heredocs for readability](https://www.techrepublic.com/article/use-heredoc-in-shell-scripts/)
- `<` *redirect input*
- `>` *redirect output*
- `<<` *read input until empty line --* **? doesn't update history ?**
- `>>` *redirect and append*
- **signals :**
- `^C` *close process*
- `^D` *exit minishell*
- `^\` *do nothing*
- **builtins (can't be executed in child process) :**
- `cd <relative path>`
- `cd <absolute path>`
- `pwd`
- `export`
- `unset`
- ~~`exit`~~
- **builtins (don't need to be) :** [source](https://git.42l.fr/Fabien/minishell)
- `env`
- ~~`echo`~~
- `echo -n`
- **autres :**
- `termcap` [man](https://www.gnu.org/software/termutils/manual/termcap-1.3/html_chapter/termcap_toc.html)
- `readline` [man](https://tiswww.case.edu/php/chet/readline/rltop.html) / [second source](https://tiswww.case.edu/php/chet/readline/README)
*[\go to sommaire](#markdown-header-sommaire)*
## 2. lexer (lexique analyser :
---
[tutorial on fork and exec](https://www.youtube.com/watch?v=O1UOWScmqxg)
[wait for all childs to terminate](https://stackoverflow.com/questions/19461744/how-to-make-parent-wait-for-all-child-processes-to-finish)
[close pipes in child AND parents](https://stackoverflow.com/questions/33884291/pipes-dup2-and-exec)
[how a shell works](https://www.cs.purdue.edu/homes/grr/SystemsProgrammingBook/Book/Chapter5-WritingYourOwnShell.pdf)
### 2.1 methode arbre binaire :
[transformer arbre normal en arbre binaire](https://fr.wikipedia.org/wiki/Arbre_binaire#Transformation_d'un_arbre_quelconque_en_un_arbre_binaire)
```text
arbre lexical :
all
. pipes
. . redirections (program function or file)
. . . arguments (nom arg arg arg ...)
. . . .
EXEMPLE : . .
[< file ./prgrm 'arg1 '$VARIABLE" arg3" | grep "word.$EXTENSION" | wc -l > file]
. [< file ./prgrm 'arg1 'arg2" arg3"]
. . [file]
. . [./prgrm 'arg1 'arg2" arg3"]
. . . [./prgrm]
. . . ['arg1 'arg2" arg3"]
. [grep "word.md"]
. . . [grep]
. . . ["word.md"]
. [wc -l > file]
. . [file]
. . [wc -l]
. . . [wc]
. . . [-l]
```
*[\go to sommaire](#markdown-header-sommaire)*
> export TEST=""
> ./test_argv $TEST foo
argv[0] : [./test_argv]
argv[1] : [foo]
> export TEST=" bar "
> ./test_argv foo"$TEST"foo
argv[0] : [./test_argv]
argv[1] : [foo bar foo]
> export TEST="bar"
> ./test_argv "foo "$TEST" foo"
argv[0] : [./test_argv]
argv[1] : [foo bar foo]
## 3. gerer les quotes et la separation des arguments :
---
### 3.1 tentative methode 1 :
#### 3.1.1 pseudo code :
```text
q = 0 // first quote
c = 0 // count
i = 0
while (str[i])
{
if (str[i] == ')
{
if (q == ')
{
c--;
if (c == 0)
{
q = 0;
create_new_substr;
}
}
else
{
c++;
if (q == 0)
q = ';
}
}
if (str[i] == ")
{
if (q == ")
{
c--;
if (c == 0)
{
q = 0;
create_new_substr;
}
}
else
{
c++;
if (q == 0)
q = ";
}
}
i++;
}
```
*[\go to sommaire](#markdown-header-sommaire)*
#### 3.1.2 application :
```text
['][a][r][g][1][ ]['][a][r][g][2]["][ ][a][r][g][3]["]
c = 0 . . . . . . . . . . . . . . . . . .
c = 1 . . . . . . . . . . . . . . . . . str[i] == ' ; q == 0 c == 0 -> c++; q = '
c = . 1 . . . . . . . . . . . . . . . . str[i] != ' | " ; ->
c = . . 1 . . . . . . . . . . . . . . . str[i] != ' | " ; ->
c = . . . 1 . . . . . . . . . . . . . . str[i] != ' | " ; ->
c = . . . . 1 . . . . . . . . . . . . . str[i] != ' | " ; ->
c = . . . . . 1 . . . . . . . . . . . . str[i] != ' | " ; ->
c = . . . . . . 0 . . . . . . . . . . . str[i] == ' ; q == ' c == 1 -> c--; q = 0;
arg1 = [a][r][g][1][ ]
c = . . . . . . . 0 . . . . . . . . . . str[i] != ' | " ; ->
c = . . . . . . . . 0 . . . . . . . . . str[i] != ' | " ; ->
c = . . . . . . . . . 0 . . . . . . . . str[i] != ' | " ; ->
c = . . . . . . . . . . 0 . . . . . . . str[i] != ' | " ; ->
c = . . . . . . . . . . . 1 . . . . . . str[i] == " ; q != " c == 0 -> c++; q = ";
arg2 = [a][r][g][2]
c = . . . . . . . . . . . . 1 . . . . . str[i] != ' | " ; ->
c = . . . . . . . . . . . . . 1 . . . . str[i] != ' | " ; ->
c = . . . . . . . . . . . . . . 1 . . . str[i] != ' | " ; ->
c = . . . . . . . . . . . . . . . 1 . . str[i] != ' | " ; ->
c = . . . . . . . . . . . . . . . . 1 . str[i] != ' | " ; ->
c = . . . . . . . . . . . . . . . . . 0 str[i] == " ; q == " c == 1 -> c--; q = 0;
arg3 = [ ][a][r][g][3]
['][a]["][r]['][g][']["][1][']
c = 0 . . . . . . . . . .
c = 1 . . . . . . . . . str[i] == ' ; q == 0 c == 0 -> c++; q = '
c = . 1 . . . . . . . . str[i] != ' | " ; ->
c = . . 2 . . . . . . . str[i] == " ; q != " c == 1 -> c++;
c = . . . 2 . . . . . . str[i] != ' | " ; ->
c = . . . . 3 . . . . . str[i] == ' | " ; q == ' c == 2 -> c++;
c = . . . . . 3 . . . . str[i] != ' | " ; ->
c = . . . . . . 2 . . . str[i] == ' ; q == ' c == 3 -> c--; q = 0;
c = . . . . . . . 1 . . str[i] == " ; q != " c == 2 ->
ERROR ...
c = . . . . . . . . 1 . str[i] != ' | " ; ->
c = . . . . . . . . . 0 str[i] != ' | " ; ->
```
*[\go to sommaire](#markdown-header-sommaire)*
#### 3.1.3 erreur :
-> comment le programme sait que cette fois il doit decrementer "c" ?
en retenant dans l'ordre toutes les dernieres valeurs de "q" !
-> donc plutot partir sur une recursive
*[\go to sommaire](#markdown-header-sommaire)*
### 3.2 tentative methode 2 :
#### 3.2.1 deroulement :
```text
.--------------------------------------------.
: .--------------------------------------. :
: : .--------------------------------. : :
: : : .--------. .--------. : : :
: : : .--. : .--. : : .--. : : : :
'__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
```
-> identifier les paires de quotes ou dquotes
-> piège :
```text
| |
.--. .--. v v .--.
'__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
```
0. envoyer une copie de la str dans une fonction
1. chercher la premiere pair
2. l'effacer
3. recommencer en boucle
4. stop quand la premier quote a trouvé sa paire
5. renvoyer l'emplacement de la pair
*[\go to sommaire](#markdown-header-sommaire)*
#### 3.2.2 application :
```text
.--.
1 : '__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
.--.
2 : '__"__'________"__'__'__"__"__'__'__"__'__"__'
.--------.
3 : '__"__'________"________"__"__'__'__"__'__"__'
.--.
4 : '__"__'____________________"__'__'__"__'__"__'
.--------.
5 : '__"__'____________________"________"__'__"__'
.--------------------------------.
6 : '__"__'________________________________'__"__'
.--------------------------------------.
7 : '__"______________________________________"__'
.--------------------------------------------.
8 : '____________________________________________'
```
*[\go to sommaire](#markdown-header-sommaire)*
### 3.3 comportement reel chelou :
```text
echo "_"
_
echo "_'_'_"
_'_'_
echo "_'_"_"_'_"
_'___'_
echo "_'_"_'_'_"_'_"
_'_____'_
echo "_'_"_'_"_"_'_"_'_"
_'___"_"___'_
echo "_'_"_"_"_"_'_"
_'_____'_
echo "_'_"_'_"_"_"_"_'_"_'_"
_'___"_"_"_"___'_
echo "_'_"_'_"_'_'_"_'_"_'_"
_'___"___"___'_
echo "_'_"_'_"_'_"_"_'_"_'_"_'_"
_'___"_____"___'_
echo "_'_"_'_"_'_"_'_'_"_'_"_'_"_'_"
_'___"___'_'___"___'_
echo "_'_"_'_"_'_"_'_"_"_'_"_'_"_'_"_'_"
_'___"___'___'___"___'_
echo "_'_"_'_"_'_"_'_"_'_'_"_'_"_'_"_'_"_'_"
_'___"___'_____'___"___'_
echo "_'_"_'_"_'_"_'_"_'_"_"_'_"_'_"_'_"_'_"_'_"
_'___"___'___"_"___'___"___'_
```
*[\go to sommaire](#markdown-header-sommaire)*
## 4. notes :
---
**idea about malloc protection :**
have them(malloc and similar) done in a specific function that would check their return and accordingly exit the program or continue
-> so that it can be done in one line
void calloc_or_exit(int num, int size);
and possibly give it a pointer to a function that will clean before exit
void calloc_or_exit(int num, int size, void (*f)(void *ptr), void *ptr);
---
Ordre Interpreteur :
1) Couper les mots (comment faire ? je ne vois pas comment gerer ce genre de bordel ci dessous)
```
shell@prompt> ./arg_test 'mot1 '$NAME" mot2"
argc = 2
argv[0] = |./arg_test|
argv[1] = |mot1 Tour-Lemdows10 mot2|
shell@prompt>
```
2) $ - Env Vars Expand. if $VAR not set, expand to nothing("").
Dont save it as "" argument for fonctions, just delete.
*[\go to sommaire](#markdown-header-sommaire)*
--------------
Commandes dans variables d'env fonctionne :
```
shell@prompt> export VAR_TEST="echo"
shell@prompt> $VAR_TEST "string :)"
string :)
shell@prompt>
```
*[\go to sommaire](#markdown-header-sommaire)*
--------------
l'expension des variables dans des variables est fait au moment de export(),
donc pas de recursivité infini et de prise de tête au moment de l'interpretation.
Il suffit de faire "une passe" pour dévelloper les variables,
aucun besoin de refaire des passes succesives pour d'éventuels nouvelles variables aprés dévellopement :
```
export :
export VAR_TEST="test $NAME"
dans l'env :
NAME="Tour-Lemdows10"
VAR_TEST="test Tour-Lemdows10"
export :
export NAME="Un nouveau nom"
dans l'env :
NAME="Un nouveau nom"
VAR_TEST="test Tour-Lemdows10"
```
```
export :
export VAR_TEST="test $VAR_TEST"
dans l'env :
VAR_TEST="test test Tour-Lemdows10"
export :
export VAR_TEST="test $VAR_TEST"
dans l'env :
VAR_TEST="test test test Tour-Lemdows10"
```
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
Tests pour Hugo, pour illustrer les pipes simultanés :
```
sleep 3 ; sleep 3 ; sleep 3 ; sleep 3
sleep 3 | sleep 3 | sleep 3 | sleep 3
sleep 5 ; ls | wc -l
sleep 5 | ls | wc -l
```
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
argv passé à execv(), telle quelle ou aprés avoir trouvé le PATH ?
exemple, si j'apelle "cat file.txt", dans un shell genre bash/zsh,
la commande cat recoit t'elle :
```
argv[0] == "cat"
argv[1] == "file.txt"
```
OU
```
argv[0] == "/bin/cat"
argv[1] == "file.txt"
```
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
A test sur bash et minishell :
echo "phrase quelquonque" > file1 > file2 > file3
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
Pour les builtins dans une commande simple :
1) detecter la commande builtin
2) Ne pas fork() et execv().
A la place, chercher la fonction aproprié dans un tableau contenant les pointeurs vers les fonctions builtins.
Puis appeler la fonction dans le genre : builtin(ft_arrlen(cmd->argv), cmd->argv, &c).
Pour les builtins dans une commande complexe (pipes, redirections, here doc, ...) :
1) detecter la commande builtin
2) fork()
3) Ne pas execv().
A la place, chercher la fonction aproprié dans un tableau contenant les pointeurs vers les fonctions builtins.
Puis appeler la fonction dans le genre : builtin(ft_arrlen(cmd->argv), cmd->argv, &c).
4) aprés la fin de la commande, free toute la mémoire du sous_processus, puis quitter le sous_processus en renvoyant le return de la commande builtin.
par exemple comme ça :
free_exit(&c, builtin(ft_arrlen(cmd->argv), cmd->argv, &c))
Peut-être faire un champ "void *builtin_command" dans une struct "cmd" pour contenir l'adresse de la fonction builtin.
```
typedef struct s_cmd
{
char **argv;
pid_t pid;
void *builtin_command;
} t_cmd;
```
Si la commande n'est pas builtin
cmd->builtin_command == NULL.
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
tester comment ce comporte minishell aprés le crash d'une commande (message sigfault comme dans bash ? Autres ?)
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
Implementer les exit status dans les builtins
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
EDIT : Aprés reflexion et verification, ça semble en effet le mieux a faire.
En l'etat le return de la derniere fonction marche correctement, j'ai verifier pas de problemes.
Si le child est deja fini avant l'apelle de wait, ça return quand même.
Cependant, pour optimiser la liberation des resources dés que possible,
il semble plus logique de liberer les sous_processus dés qu'ils ont terminés,
et donc, pas nécessairement dans l'ordre de la pipeline.
Donc, un waitpid() sur la derniere commande pour sauvegarder le retour,
puis wait() pour les autres, l'ordre n'ayant plus d'importance.
Revoir le wait() de mon pipex. Il n'est peut être pas correct.
En effet, j'attend que le premier process se ferme avec waitpid(), puis le deuxiéme, le troisiéme, ...
Mais en faite, il vaudrait peut être mieux attendre qu'un sous process QUELQUONQUE se ferme, puis le suivant, et le suivant, ...
Vu le fonctionnement des pipes, je crois que ce n'est pas toujours la premiere commande qui ce termine en premier,
et donc, qu'il ne faudrait pas attendre la fin de la premiere commande en particulier,
mais d'une commande QUELQUONQUE avec wait() plutot que waitpid().
IDÉE :
Attendre avec waitpid() la derniere commande pour obtenir son status, puis wait() en boucle les autres commandes,
et enfin renvoyer le status.
*[\go to sommaire](#markdown-header-sommaire)*
-------------------
Faire des test avec
"env -i ./minishell"
pour voir si ça ne crash pas.
Normal si le comportement attendu n'est pas correct (en l'absence de PATH et tout ça) mais ça ne devrait pas crasher pour autant.
*[\go to sommaire](#markdown-header-sommaire)*

12
echo
View File

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

View File

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

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/10/13 16:09:32 by lperrey ### ########.fr */ /* Updated: 2021/11/27 09:09:31 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,6 +15,7 @@
# include "libft.h" # include "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>
@@ -26,15 +27,19 @@
# 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>
# include <stdio.h> // sudo apt install libreadline-dev
# include <readline/readline.h> // sudo apt install libreadline-dev # include <readline/readline.h>
# include <readline/history.h> # include <readline/history.h>
# include "minishell_structs.h" # include <stdio.h>
# include "minishell_macro.h" # include "minishell_macro.h"
# include "minishell_structs.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"
@@ -52,8 +57,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(), ioctl(), ** isatty(), ttyname(), ttyslot(), tcsetattr(), tcgetattr()
** tcsetattr(), tcgetattr() ** <sys/ioctl.h>: ioctl()
** <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/10/08 03:01:43 by lperrey ### ########.fr */ /* Updated: 2021/11/27 10:43:43 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -18,4 +18,37 @@
# define PROMPT_CHEVRON "> " # define PROMPT_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,33 +6,99 @@
/* 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/10/19 23:41:25 by hulamy ### ########.fr */ /* Updated: 2021/12/22 19:28:07 by lperrey ### ########.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 *envp[]); int init(t_all *c, char *argv[]);
char *update_prompt(char *prompt_base);
int retrieve_path(char **path_stock[]);
void set_signals_behaviour(void);
// Shell modes
void shell_loop(t_all *c);
void shell_script(t_all *c, int script_fd);
// Lexer
t_token *lexing(char *input);
// Parser
t_cmd **parsing(t_token *token_list, int script_fd);
int valid_syntax(t_token *token_list);
int valid_token(t_token **token_list, enum e_token_id token_id);
int valid_command_separator(const t_token *token_list);
size_t count_pipes(t_token *token_list);
t_cmd **pipeline_alloc(size_t cmd_nbr);
int pipeline_fill_argv(t_token *token_list, t_cmd **pipeline);
int expansions(t_token *token_list, t_cmd **pipeline);
int token_expansions(t_token *t);
int redirections(t_token *token_list, t_cmd **pipeline, int script_fd);
// Exec
int exec_cmd_line(t_all *c);
int pipeline(t_all *c);
int cmd_find_access(t_cmd *cmd, char *path[]);
int cmd_exec_in_subshell(t_cmd *cmd, t_all *c);
void wait_subshell(pid_t last_cmd_pid);
int simple_command_builtin(t_cmd *cmd, t_all *c);
// Builtins // Builtins
int builtin_env(int argc, char *argv[], t_all *c); int builtin_cd(int argc, char *argv[], t_all *c);
int builtin_pwd(int argc, char *argv[], t_all *c);
int builtin_export(int argc, char *argv[], t_all *c);
int export_var(char *arg);
int builtin_unset(int argc, char *argv[], t_all *c);
int builtin_exit(int argc, char *argv[], t_all *c); int builtin_exit(int argc, char *argv[], t_all *c);
int builtin_env(int argc, char *argv[], t_all *c);
int builtin_echo(int argc, char *argv[], t_all *c);
// Free // Free
int free_exit(t_all *c, int exit_status); int exit_free(t_all *c, int exit_status);
void free_pipeline(t_cmd **pipeline_ptr[]);
void close_pipeline_fd(t_cmd *pipeline[]);
void close_cmd_fd(t_cmd *cmd);
void close_stdio(void);
typedef void (*t_free_f)(void *); // generic
// Error wrappers
int shell_error(char *s1, char *s2, char *s3, int ret_val);
int shell_perror(char *s1, char *s2, char *s3, int ret_val);
int ft_reti_perror_io(int ret, char *err_str, char *io_file);
// Generic // 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);
// pipes hugo char **ft_split_quotes(char const *s, char c);
void pipes_hugo(char *input, t_all *c); char *ft_strdup_quotes(const char *s);
// parser hugo
void **cmd_path(char **argv, char **envp); // Signals handler
int handle_fd(char **input, int i, int fdin, t_cmd *cmd); void sigint_handler_interactive(int signum);
t_list *parser(char *input, char **envp); void sigint_handler_heredoc(int signum);
// last_exit_status
int set_last_exit_status(int new_value);
int get_last_exit_status(void);
#endif #endif

View File

@@ -6,30 +6,43 @@
/* 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/10/20 09:11:41 by hulamy ### ########.fr */ /* Updated: 2021/12/20 22:13:45 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef MINISHELL_STRUCTS_H #ifndef MINISHELL_STRUCTS_H
# define MINISHELL_STRUCTS_H # define MINISHELL_STRUCTS_H
typedef struct s_all struct s_all;
typedef struct s_token
{ {
char **envp; char *content;
char *prompt_base; struct s_token *next;
char *prompt; enum e_token_id id;
} t_all; } t_token;
typedef int (*t_builtin_f)(int,char **,struct s_all *);
typedef struct s_cmd typedef struct s_cmd
{ {
char **argv; char **argv;
pid_t pid; char *path;
void *builtin; t_builtin_f builtin_f;
int pipe_in; int fd_in;
int pipe_out; int fd_out;
int fd_redirect; pid_t pid;
int fd_in; int error;
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/10 20:58:28 by lperrey ### ########.fr */ /* Updated: 2021/10/19 20:30:34 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,7 +15,7 @@
# include "minishell_macro.h" # include "minishell_macro.h"
# define U_PROMPT_END PROMPT_EURO # define U_PROMPT_END PROMPT_CHEVRON
# 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: 1401fddfcd...af88c1ce23

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 KiB

82
srcs/builtins/cd.c Normal file
View File

@@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/04 19:31:19 by lperrey #+# #+# */
/* Updated: 2021/12/20 21:51:00 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#define CMD "builtin_cd"
static int change_prompt(t_all *c);
static int change_env_pwd(void);
int builtin_cd(int argc, char *argv[], t_all *c)
{
char *dir;
if (argc > 2)
return (shell_error("cd: ", "too many arguments", "", EXIT_FAILURE));
else if (argc < 2 || ft_strncmp(argv[1], "~", 2) == 0)
{
dir = getenv("HOME");
if (!dir)
return (shell_error("cd: ", "HOME not set", "", EXIT_FAILURE));
}
else if (argc == 2)
dir = argv[1];
if (chdir(dir) == -1)
return (shell_perror("cd: ", dir, ": ", EXIT_FAILURE));
if (change_prompt(c) == -1)
return (ft_reti_perror(EXIT_FAILURE, CMD", change_prompt()"));
if (change_env_pwd() == -1)
return (ft_reti_perror(EXIT_FAILURE, CMD", change_env_pwd()"));
return (EXIT_SUCCESS);
}
static int change_prompt(t_all *c)
{
char *tmp;
tmp = update_prompt(c->prompt_base);
if (!tmp)
return (-1);
free(c->prompt);
c->prompt = tmp;
return (0);
}
static int change_env_pwd(void)
{
char *tmp;
int ret;
tmp = getenv("PWD");
if (tmp)
{
tmp = ft_strjoin("OLDPWD=", tmp);
if (!tmp)
return (-1);
ret = export_var(tmp);
free(tmp);
if (ret == -1)
return (-1);
}
tmp = getcwd(NULL, 0);
if (!tmp)
return (-1);
tmp = ft_strjoinfree_s2("PWD=", tmp);
if (!tmp)
return (-1);
ret = export_var(tmp);
free(tmp);
if (ret == -1)
return (-1);
return (0);
}

47
srcs/builtins/echo.c Normal file
View File

@@ -0,0 +1,47 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* echo.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/21 16:37:44 by lperrey #+# #+# */
/* Updated: 2021/10/21 20:22:22 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
enum e_echo_options
{
BIT_N = 01,
};
int builtin_echo(int argc, char *argv[], t_all *c)
{
int i;
int options;
(void)argc;
(void)c;
options = 0;
i = 1;
while (argv[i] && argv[i][0] == '-')
{
if (ft_isinset_str(&argv[i][1], "n"))
options = options | BIT_N;
else
break ;
i++;
}
while (argv[i])
{
ft_putstr_fd(argv[i], 1);
i++;
if (argv[i])
write(1, " ", 1);
}
if ((options & BIT_N) == 0)
write(1, "\n", 1);
return (0);
}

View File

@@ -6,16 +6,17 @@
/* 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/10/10 07:37:29 by lperrey ### ########.fr */ /* Updated: 2021/12/01 17:19:48 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int builtin_env(int argc, char *argv[], t_all *c) // WIP int builtin_env(int argc, char *argv[], t_all *c)
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
ft_putendl_arr_fd(c->envp, 1); (void)c;
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/10/11 01:50:53 by lperrey ### ########.fr */ /* Updated: 2021/11/29 12:43:47 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int builtin_exit(int argc, char *argv[], t_all *c) // WIP int builtin_exit(int argc, char *argv[], t_all *c)
{ {
unsigned char status; unsigned char status;
int i; int i;
status = 0; status = get_last_exit_status();
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) // WIP
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 (free_exit(c, status)); return (exit_free(c, status));
} }

96
srcs/builtins/export.c Normal file
View File

@@ -0,0 +1,96 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* export.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/03 13:36:54 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:23:41 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int change_var_value(char *arg, char *var_name);
#define ERR_ID 1
#define ERR_ID_STR ": not a valid identifier"
#define CMD "builtin_export"
int builtin_export(int argc, char *argv[], t_all *c)
{
int i;
int exit_value;
int ret;
(void)argc;
exit_value = EXIT_SUCCESS;
i = 1;
while (argv[i])
{
ret = export_var(argv[i]);
if (ret == -1)
return (ft_reti_perror(EXIT_FAILURE, CMD", export_var()"));
else if (ret == ERR_ID)
exit_value = EXIT_FAILURE;
if (ft_strncmp(argv[i], "PATH=", 5) == 0)
retrieve_path(&c->path);
i++;
}
return (exit_value);
}
// in complete shell, must mark arguments for export
// (Not implemented in minishell)
// arg == var_name[=value]
// return "-1" on alloc error
int export_var(char *arg)
{
char **var_split;
int ret;
if (arg[0] != '_' && !ft_isalpha(arg[0]))
return (shell_error("export: ", arg, ERR_ID_STR, ERR_ID));
var_split = ft_split(arg, '=');
if (!var_split)
return (-1);
if (!ft_is_posix_name(var_split[0]))
{
shell_error("export: ", var_split[0], ERR_ID_STR, 0);
ft_free_2d_arr(var_split);
return (ERR_ID);
}
ret = 0;
if (ft_strchr(arg, '='))
ret = change_var_value(arg, var_split[0]);
ft_free_2d_arr(var_split);
return (ret);
}
static int change_var_value(char *arg, char *var_name)
{
int env_position;
char *tmp;
env_position = ft_getenv_position(var_name);
if (environ[env_position] == NULL)
{
environ = ft_resize_2d_arr(environ, 1);
if (!environ)
return (ft_reti_perror(-1, CMD", ft_resize_2d_arr()"));
}
tmp = ft_strdup(arg);
if (!tmp)
return (ft_reti_perror(-1, CMD", ft_strdup()"));
free(environ[env_position]);
environ[env_position] = tmp;
return (EXIT_SUCCESS);
}
/*
environment variables must be POSIX NAME :
3.235 Name
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
#tag_03_235
*/

29
srcs/builtins/pwd.c Normal file
View File

@@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pwd.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/04 19:15:36 by lperrey #+# #+# */
/* Updated: 2021/12/04 20:22:49 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int builtin_pwd(int argc, char *argv[], t_all *c)
{
char *working_dir;
(void)argc;
(void)argv;
(void)c;
working_dir = getcwd(NULL, 0);
if (!working_dir)
return (ft_reti_perror(EXIT_FAILURE, "builtin_pwd, getcwd()"));
write(1, working_dir, ft_strlen(working_dir));
write(1, "\n", 1);
free(working_dir);
return (EXIT_SUCCESS);
}

61
srcs/builtins/unset.c Normal file
View File

@@ -0,0 +1,61 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* unset.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/05 17:05:05 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:23:50 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int unset_env_var(char *arg);
int builtin_unset(int argc, char *argv[], t_all *c)
{
int i;
int exit_value;
(void)argc;
(void)c;
exit_value = EXIT_SUCCESS;
i = 1;
while (argv[i])
{
if (unset_env_var(argv[i]) == EXIT_FAILURE)
exit_value = EXIT_FAILURE;
if (ft_strncmp(argv[i], "PATH", 4 + 1) == 0)
retrieve_path(&c->path);
i++;
}
return (exit_value);
}
static int unset_env_var(char *arg)
{
int env_position;
if (!ft_is_posix_name(arg))
{
shell_error("unset: ", arg, ": not a valid identifier", 0);
return (EXIT_FAILURE);
}
env_position = ft_getenv_position(arg);
free(environ[env_position]);
while (environ[env_position])
{
environ[env_position] = environ[env_position + 1];
env_position++;
}
return (EXIT_SUCCESS);
}
/*
environment variables must be POSIX NAME :
3.235 Name
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
#tag_03_235
*/

29
srcs/exec/exec_cmd_line.c Normal file
View File

@@ -0,0 +1,29 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* exec_cmd_line.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/01 16:07:48 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int exec_cmd_line(t_all *c)
{
if (!pipeline(c))
{
free_pipeline(&c->pipeline);
return (0);
}
return (1);
}
/*
2.9.1 Simple Commands - Command Search and Execution
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
#tag_18_09_01_01
*/

111
srcs/exec/find_access.c Normal file
View File

@@ -0,0 +1,111 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* find_access.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/22 15:03:31 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int search_cmd_path(char *cmd_name, char **cmd_path,
char *path[]);
static t_builtin_f search_builtin(char *cmd_name);
static int handle_access_error(char *file_name);
/*
* 2.8.2 Exit Status for Commands
* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
* #tag_18_08_02
*/
int cmd_find_access(t_cmd *cmd, char *path[])
{
if (ft_strchr(cmd->argv[0], '/'))
{
if (access(cmd->argv[0], X_OK) == -1)
cmd->error = handle_access_error(cmd->argv[0]);
else
{
cmd->path = ft_strdup(cmd->argv[0]);
if (!cmd->path)
return (0);
}
}
else
{
cmd->builtin_f = search_builtin(cmd->argv[0]);
if (cmd->builtin_f)
return (1);
if (search_cmd_path(cmd->argv[0], &cmd->path, path) == -1)
return (0);
if (!cmd->path)
{
cmd->error = EXIT_CMD_NOT_FOUND;
shell_error(cmd->argv[0], ": ", "command not found", 0);
}
}
return (1);
}
static int search_cmd_path(char *cmd_name, char **cmd_path, char *path[])
{
int i;
if (!path)
return (1);
cmd_name = ft_strjoin("/", cmd_name);
if (!cmd_name)
return (ft_reti_perror(-1, "search_cmd_path()"));
i = 0;
while (path[i])
{
*cmd_path = ft_strjoin(path[i], cmd_name);
if (!*cmd_path)
return (ft_reti_perror(-1, "search_cmd_path()"));
if (access(*cmd_path, X_OK) == 0)
break ;
else
ft_free_null(cmd_path);
i++;
}
free(cmd_name);
return (1);
}
static t_builtin_f search_builtin(char *cmd_name)
{
if (ft_strncmp(cmd_name, "echo", 4 + 1) == 0)
return (&builtin_echo);
else if (ft_strncmp(cmd_name, "cd", 2 + 1) == 0)
return (&builtin_cd);
else if (ft_strncmp(cmd_name, "pwd", 3 + 1) == 0)
return (&builtin_pwd);
else if (ft_strncmp(cmd_name, "export", 6 + 1) == 0)
return (&builtin_export);
else if (ft_strncmp(cmd_name, "unset", 5 + 1) == 0)
return (&builtin_unset);
else if (ft_strncmp(cmd_name, "env", 3 + 1) == 0)
return (&builtin_env);
else if (ft_strncmp(cmd_name, "exit", 4 + 1) == 0)
return (&builtin_exit);
return (NULL);
}
static int handle_access_error(char *file_name)
{
int tmp;
tmp = errno;
shell_perror(file_name, ": ", "", 0);
errno = tmp;
if (errno == EACCES)
return (EXIT_CMD_NOT_EXE);
else if (errno == ENOENT)
return (EXIT_CMD_NOT_FOUND);
return (1);
}

111
srcs/exec/pipeline.c Normal file
View File

@@ -0,0 +1,111 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipeline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/20 18:08:16 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int open_pipes(t_cmd *pipeline[]);
static int pipeline_find_access(t_cmd *pipeline[], char *path[]);
static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c);
int pipeline(t_all *c)
{
t_cmd **pipeline;
int ret;
pipeline = c->pipeline;
if (!open_pipes(pipeline))
return (0);
if (!pipeline_find_access(pipeline, c->path))
return (0);
if (ft_2d_arrlen(pipeline) > 1)
wait_subshell(pipeline_exec(pipeline, c));
else
{
if (pipeline[0]->error)
set_last_exit_status(pipeline[0]->error);
else if (pipeline[0]->builtin_f)
{
ret = simple_command_builtin(pipeline[0], c);
if (ret != EXIT_SUCCESS)
set_last_exit_status(ret);
}
else
wait_subshell(pipeline_exec(pipeline, c));
}
free_pipeline(&c->pipeline);
return (1);
}
static int open_pipes(t_cmd *pipeline[])
{
int i;
int pipes[2];
i = 0;
while (pipeline[i] && pipeline[i + 1])
{
if (pipe(pipes) == -1)
return (ft_reti_perror(0, "pipe()"));
if (pipeline[i]->fd_out == STDOUT_FILENO)
pipeline[i]->fd_out = pipes[STDOUT_FILENO];
else
if (close(pipes[STDOUT_FILENO]) == -1)
perror("close()");
if (pipeline[i + 1]->fd_in == STDIN_FILENO)
pipeline[i + 1]->fd_in = pipes[STDIN_FILENO];
else
if (close(pipes[STDIN_FILENO]) == -1)
perror("close()");
i++;
}
return (1);
}
static int pipeline_find_access(t_cmd *pipeline[], char *path[])
{
int i;
i = 0;
while (pipeline[i])
{
if (!pipeline[i]->error && pipeline[i]->argv[0])
{
if (!cmd_find_access(pipeline[i], path))
return (0);
}
i++;
}
return (1);
}
static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c)
{
int i;
int ret;
i = 0;
while (pipeline[i])
{
if (!pipeline[i]->error && pipeline[i]->argv[0])
{
ret = cmd_exec_in_subshell(pipeline[i], c);
if (ret != EXIT_SUCCESS)
exit_free(c, ret);
}
close_cmd_fd(pipeline[i]);
i++;
}
i -= 1;
if (pipeline[i]->error)
set_last_exit_status(pipeline[i]->error);
return (pipeline[i]->pid);
}

View File

@@ -0,0 +1,63 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* simple_cmd_builtin.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/01 16:49:37 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int restore_stdio(int stdin_dup, int stdout_dup);
int simple_command_builtin(t_cmd *cmd, t_all *c)
{
int stdin_dup;
int stdout_dup;
stdin_dup = 0;
stdout_dup = 0;
if (cmd->fd_in != STDIN_FILENO)
{
stdin_dup = dup(STDIN_FILENO);
if (stdin_dup == -1)
return (ft_reti_perror(EXIT_FAILURE, "dup()"));
if (dup2(cmd->fd_in, STDIN_FILENO) == -1)
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
}
if (cmd->fd_out != STDOUT_FILENO)
{
stdout_dup = dup(STDOUT_FILENO);
if (stdout_dup == -1)
return (ft_reti_perror(EXIT_FAILURE, "dup()"));
if (dup2(cmd->fd_out, STDOUT_FILENO) == -1)
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
}
set_last_exit_status(cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c));
if (!restore_stdio(stdin_dup, stdout_dup))
return (EXIT_FAILURE);
return (EXIT_SUCCESS);
}
static int restore_stdio(int stdin_dup, int stdout_dup)
{
if (stdin_dup)
{
if (dup2(stdin_dup, STDIN_FILENO) == -1)
return (ft_reti_perror(0, "dup2()"));
if (close(stdin_dup) == -1)
return (ft_reti_perror(0, "close()"));
}
if (stdout_dup)
{
if (dup2(stdout_dup, STDOUT_FILENO) == -1)
return (ft_reti_perror(0, "dup2()"));
if (close(stdout_dup) == -1)
return (ft_reti_perror(0, "close()"));
}
return (1);
}

55
srcs/exec/subshell_exec.c Normal file
View File

@@ -0,0 +1,55 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* subshell_exec.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/22 22:12:16 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static void exec_builtin(t_cmd *cmd, t_all *c);
int cmd_exec_in_subshell(t_cmd *cmd, t_all *c)
{
struct sigaction signal_behaviour;
cmd->pid = fork();
if (cmd->pid == -1)
perror("fork()");
if (cmd->pid == 0)
{
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
signal_behaviour.sa_handler = SIG_DFL;
sigaction(SIGINT, &signal_behaviour, NULL);
sigaction(SIGQUIT, &signal_behaviour, NULL);
if (cmd->fd_in != STDIN_FILENO)
if (dup2(cmd->fd_in, STDIN_FILENO) == -1)
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
if (cmd->fd_out != STDOUT_FILENO)
if (dup2(cmd->fd_out, STDOUT_FILENO) == -1)
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
close_pipeline_fd(c->pipeline);
if (cmd->builtin_f)
exec_builtin(cmd, c);
else if (execve(cmd->path, cmd->argv, environ) == -1)
return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0]));
}
return (EXIT_SUCCESS);
}
static void exec_builtin(t_cmd *cmd, t_all *c)
{
struct sigaction signal_behaviour;
int ret;
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &signal_behaviour, NULL);
ret = cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c);
exit_free(c, ret);
}

65
srcs/exec/subshell_wait.c Normal file
View File

@@ -0,0 +1,65 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* subshell_wait.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/22 15:38:01 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static void handle_signal_status(int wstatus);
static int handle_wait_error(void);
void wait_subshell(pid_t last_cmd_pid)
{
int wstatus;
int ret;
wstatus = 0;
if (last_cmd_pid > 0)
{
if (waitpid(last_cmd_pid, &wstatus, 0) == -1)
perror("waitpid()");
if (WIFEXITED(wstatus))
set_last_exit_status(WEXITSTATUS(wstatus));
if (WIFSIGNALED(wstatus))
handle_signal_status(wstatus);
}
ret = 0;
while (ret != -1)
{
ret = wait(&wstatus);
if (ret == -1)
ret = handle_wait_error();
}
if (get_last_exit_status() == EXIT_SIGNAL + SIGSEGV)
ft_putstr_fd("Segmentation fault (core dumped)\n", STDERR_FILENO);
}
static void handle_signal_status(int wstatus)
{
int signum;
signum = WTERMSIG(wstatus);
set_last_exit_status(EXIT_SIGNAL + signum);
if (signum == SIGINT)
write(STDOUT_FILENO, "\n", 1);
if (signum == SIGQUIT)
ft_putstr_fd("Quit (core dumped)\n", STDERR_FILENO);
}
static int handle_wait_error(void)
{
if (errno == ECHILD)
return (-1);
else if (errno == EINTR)
return (0);
else
perror("wait()");
return (-1);
}

View File

@@ -0,0 +1,67 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_2d_arr_func.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/16 03:43:33 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
// Replace ft_arrlen()
size_t ft_2d_arrlen(void *ptr)
{
size_t len;
char **arr;
arr = (char **)ptr;
len = 0;
while (arr[len] != NULL)
len++;
return (len);
}
void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *))
{
unsigned int i;
char **arr;
char **new_arr;
new_arr = ft_calloc(ft_2d_arrlen(ptr) + 1, sizeof (void *));
if (!new_arr)
return (NULL);
arr = (char **)ptr;
i = 0;
while (arr[i])
{
new_arr[i] = dup_func(arr[i]);
if (!new_arr[i])
return (ft_retp_free(NULL, new_arr, ft_free_2d_arr));
i++;
}
return (new_arr);
}
void *ft_resize_2d_arr(void *ptr, size_t add_nbr)
{
unsigned int i;
char **arr;
char **new_arr;
new_arr = ft_calloc(ft_2d_arrlen(ptr) + add_nbr + 1, sizeof (void *));
if (!new_arr)
return (NULL);
arr = (char **)ptr;
i = 0;
while (arr[i])
{
new_arr[i] = arr[i];
i++;
}
free(arr);
return (new_arr);
}

View File

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

70
srcs/generic/ft_getenv.c Normal file
View File

@@ -0,0 +1,70 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_getenv.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/22 18:07:16 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
/*
** Search for an environement variable,
** and return a pointer to the first character after "env_var=" .
** Return NULL if env_var not found.
*/
char *ft_getenv(char *env_var)
{
int i;
char *tmp;
size_t env_var_len;
env_var_len = ft_strlen(env_var);
i = 0;
tmp = NULL;
while (!tmp && environ[i])
{
if (environ[i][env_var_len] == '=')
{
if (ft_strncmp(environ[i], env_var, env_var_len) == 0)
tmp = &environ[i][env_var_len + 1];
else
i++;
}
else
i++;
}
return (tmp);
}
/*
** Like ft_getenv(), but return position of env_var instead of value.
** If env_var not found, return last position of **environ (== NULL)
*/
size_t ft_getenv_position(char *env_var)
{
int i;
int found;
size_t env_var_len;
env_var_len = ft_strlen(env_var);
i = 0;
found = 0;
while (!found && environ[i])
{
if (ft_strncmp(environ[i], env_var, env_var_len) == 0)
{
if (environ[i][env_var_len] == '=')
found = 1;
else
i++;
}
else
i++;
}
return (i);
}

View File

@@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_is_posix_name.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/18 13:31:11 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int ft_is_posix_name(char *str)
{
unsigned int i;
if (!str)
return (0);
if (str[0] != '_' && !ft_isalpha(str[0]))
return (0);
i = 1;
while (str[i])
{
if (str[i] != '_' && !ft_isalnum(str[i]))
return (0);
i++;
}
return (i);
}

View File

@@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_isinset_str.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/16 03:45:50 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int ft_isinset_str(char *str, char *set)
{
size_t i;
size_t i_set;
int valid;
i = 0;
while (str[i])
{
valid = 0;
i_set = 0;
while (set[i_set] && !valid)
{
if (str[i] == set[i_set])
valid = 1;
i_set++;
}
if (!valid)
return (0);
i++;
}
return (i);
}

View File

@@ -0,0 +1,56 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_lst_func.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/16 03:45:39 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void ft_lstprint(t_list *lst, int fd)
{
while (lst)
{
ft_putendl_fd(lst->content, fd);
lst = lst->next;
}
}
t_list *ft_lstbeforelast(t_list *lst)
{
if (!lst || !lst->next)
return (NULL);
while (lst->next->next)
lst = lst->next;
return (lst);
}
/* if "content_size == 0", return lst with "lst->content == NULL" */
void *ft_lstnew_generic(size_t lst_size, size_t content_size)
{
t_list *elem;
void *content;
if (content_size == 0)
content = NULL;
else
{
content = ft_calloc(content_size, 1);
if (!content)
return (NULL);
}
elem = ft_calloc(1, lst_size);
if (!elem)
{
free(content);
return (NULL);
}
elem->content = content;
elem->next = NULL;
return (elem);
}

View File

@@ -0,0 +1,179 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_split_quotes.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/13 07:08:40 by lperrey #+# #+# */
/* Updated: 2021/12/20 16:45:10 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static size_t count_word(char const *s, char c);
static char **alloc_words(char const *s, char c, char **str_arr,
size_t words_count);
static void fill_arr(char const *s, char c, char **str_arr);
static int quote_state_change(int *quote_state, const char *s);
char **ft_split_quotes(char const *s, char c)
{
char **str_arr;
size_t words_count;
if (s == NULL)
return (NULL);
words_count = count_word(s, c);
str_arr = ft_calloc(words_count + 1, sizeof(char *));
if (!str_arr)
return (NULL);
if (!(alloc_words(s, c, str_arr, words_count)))
{
ft_free_2d_arr(str_arr);
return (NULL);
}
fill_arr(s, c, str_arr);
return (str_arr);
}
static size_t count_word(char const *s, char c)
{
unsigned int i;
size_t count;
int quote_state;
i = 0;
count = 0;
quote_state = 0;
while (s[i])
{
while (s[i] == c)
i++;
if (s[i])
count++;
while (s[i] && (s[i] != c || quote_state))
{
while (quote_state_change(&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

@@ -0,0 +1,64 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strdup_quotes.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/13 04:35:06 by lperrey #+# #+# */
/* Updated: 2021/12/20 16:29:27 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int quote_state_change(int *quote_state, const char *s);
/* Duplicate a string minus the quoting characters ['] and ["]*/
char *ft_strdup_quotes(const char *s)
{
unsigned int i;
unsigned int i_dup;
char *dup;
int quote_state;
dup = ft_calloc(ft_strlen(s) + 1, 1);
if (!dup)
return (NULL);
i = 0;
i_dup = 0;
quote_state = 0;
while (s[i])
{
while (quote_state_change(&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,12 +1,12 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* generic.c :+: :+: :+: */ /* ft_strjoinfree.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/10/08 09:28:49 by lperrey ### ########.fr */ /* Updated: 2021/12/16 03:39:09 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

35
srcs/init/init.c Normal file
View File

@@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* init.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:24:04 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void init_readline(void);
int init_shlvl(void);
void open_script_file(t_all *c, char *argv[]);
int init_prompt(t_all *c, int script_fd);
int init(t_all *c, char *argv[])
{
ft_bzero(c, sizeof (*c));
set_signals_behaviour();
init_readline();
environ = ft_dup_2d_arr(environ, (t_dup_f)ft_strdup);
if (!environ)
return (ft_reti_perror(0, "ft_dup_2d_arr(environ)"));
retrieve_path(&c->path);
if (!init_shlvl())
return (ft_reti_perror(0, "init_shlvl()"));
open_script_file(c, argv);
if (!init_prompt(c, c->script_fd))
return (ft_reti_perror(0, "init_prompt()"));
return (1);
}

View File

@@ -1,30 +1,30 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* init.c :+: :+: :+: */ /* init_prompt.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/10/10 21:56:33 by lperrey ### ########.fr */ /* Updated: 2021/12/20 22:25:46 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(t_all *c, char *envp[]) int init_prompt(t_all *c, int script_fd)
{ {
ft_bzero(c, sizeof *c); if (!script_fd && isatty(STDIN_FILENO))
c->envp = envp; {
c->prompt_base = init_prompt_base(); c->prompt_base = init_prompt_base();
if (!c->prompt_base) if (!c->prompt_base)
return (ft_reti_perror(0, "init_prompt_base() fail")); return (0);
c->prompt = init_prompt(c->prompt_base); c->prompt = update_prompt(c->prompt_base);
if (!c->prompt) if (!c->prompt)
return (ft_reti_perror(0, "init_prompt() fail")); return (0);
}
return (1); return (1);
} }
@@ -39,20 +39,32 @@ 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);
} }
static char *init_prompt(char *prompt_base) char *update_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);
} }

33
srcs/init/init_readline.c Normal file
View File

@@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* init_readline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/18 04:31:59 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int init_readline_hook(void);
void init_readline(void)
{
rl_outstream = stderr;
rl_startup_hook = init_readline_hook;
readline(NULL);
rl_startup_hook = NULL;
}
/*
** set rl_startup_hook with this, for init COLUMNS and LINES variables
** and prevent leak/double_free with **environ
*/
static int init_readline_hook(void)
{
rl_done = 1;
return (0);
}

37
srcs/init/init_shlvl.c Normal file
View File

@@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* init_shlvl.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/18 04:35:33 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int init_shlvl(void)
{
char *tmp;
int ret;
tmp = getenv("SHLVL");
if (tmp && ft_isdigit_str(tmp))
{
tmp = ft_itoa(ft_atoi(tmp) + 1);
if (!tmp)
return (0);
tmp = ft_strjoinfree_s2("SHLVL=", tmp);
if (!tmp)
return (0);
ret = export_var(tmp);
free(tmp);
}
else
ret = export_var("SHLVL=1");
if (ret == -1)
return (0);
return (1);
}

View File

@@ -0,0 +1,26 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* open_script_file.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/20 22:22:29 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:27:14 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void open_script_file(t_all *c, char *argv[])
{
if (argv[1])
{
c->script_fd = open(argv[1], O_RDONLY);
if (c->script_fd == -1)
{
shell_perror(argv[1], ": ", "", 0);
exit_free(c, EXIT_CMD_NOT_FOUND);
}
}
}

View File

@@ -0,0 +1,65 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* check_operators.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/19 08:38:55 by lperrey #+# #+# */
/* Updated: 2021/10/30 22:37:08 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int check_redirection(t_token *t, char *input, int *i, int *t_i);
static int check_pipe(t_token *t, char *input, int *i, int *t_i);
int check_operators(t_token *t, char *input, int *i, int *t_i)
{
if (*t_i != 0 && (input[*i] == '|' || input[*i] == '<' || input[*i] == '>'))
return (DELIMITE_TOKEN);
else if (check_pipe(t, input, i, t_i))
return (DELIMITE_TOKEN);
else if (check_redirection(t, input, i, t_i))
return (DELIMITE_TOKEN);
return (CONTINUE_TOKEN);
}
static int check_pipe(t_token *t, char *input, int *i, int *t_i)
{
if (input[*i] == '|')
{
t->content[(*t_i)++] = input[(*i)++];
t->id = T_PIPE;
return (1);
}
return (0);
}
static int check_redirection(t_token *t, char *input, int *i, int *t_i)
{
if (input[*i] == '<')
{
t->content[(*t_i)++] = input[(*i)++];
t->id = T_LESS;
if (input[*i] == '<')
{
t->content[(*t_i)++] = input[(*i)++];
t->id = T_DLESS;
}
return (1);
}
else if (input[*i] == '>')
{
t->content[(*t_i)++] = input[(*i)++];
t->id = T_GREAT;
if (input[*i] == '>')
{
t->content[(*t_i)++] = input[(*i)++];
t->id = T_DGREAT;
}
return (1);
}
return (0);
}

63
srcs/lexing/fill_token.c Normal file
View File

@@ -0,0 +1,63 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* fill_token.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/19 08:38:55 by lperrey #+# #+# */
/* Updated: 2021/12/01 16:00:48 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int check_operators(t_token *t, char *input, int *i, int *t_i);
static int quoting(int *quotes_state, char *input, int *i);
int fill_token(t_token *t, char *input, int *i, int *t_i)
{
static int quotes_state = 0;
if (!quotes_state)
{
if (check_operators(t, input, i, t_i) == DELIMITE_TOKEN)
return (DELIMITE_TOKEN);
}
if (quoting(&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);
}

69
srcs/lexing/lexing.c Normal file
View File

@@ -0,0 +1,69 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* lexing.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/19 08:38:55 by lperrey #+# #+# */
/* Updated: 2021/12/05 17:11:31 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int fill_token(t_token *t, char *input, int *i, int *t_i);
static int tokenize_input(t_token *t, char *input, size_t input_len);
t_token *lexing(char *input)
{
t_token *t_head;
t_token *t_tmp;
size_t input_len;
input_len = ft_strlen(input);
t_head = ft_lstnew_generic(sizeof(t_token), input_len + 1);
if (!t_head)
return (ft_retp_perror(NULL, "ft_lstnew_generic() error"));
if (!tokenize_input(t_head, input, input_len))
return (ft_lstclear((t_list **)&t_head, free));
t_tmp = (t_token *)ft_lstbeforelast((t_list *)t_head);
if (t_tmp && t_tmp->next && !t_tmp->next->id)
{
ft_lstdelone((t_list *)t_tmp->next, free);
t_tmp->next = NULL;
}
return (t_head);
}
static int tokenize_input(t_token *t, char *input, size_t input_len)
{
int i;
int t_i;
i = 0;
t_i = 0;
while (input[i])
{
if (fill_token(t, input, &i, &t_i) == DELIMITE_TOKEN && input[i] && t_i)
{
if (!t->id)
t->id = T_WORD;
t->next = ft_lstnew_generic(sizeof(t_token), input_len + 1 - i);
if (!t->next)
return (ft_reti_perror(0, "ft_lstnew_generic() error"));
t = t->next;
t_i = 0;
}
}
if (!t->id && t_i)
t->id = T_WORD;
return (1);
}
/*
2.3 Token Recognition
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
#tag_18_03
*/

View File

@@ -1,113 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:26:14 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
void close_fd(t_cmd *cmd, pid_t pid) int g_switch_heredoc_sigint;
{
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);
}
}
void exec_cmd(char **envp, t_list *cmd_list) int main(int argc, char *argv[])
{
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;
(void)argv; if (!init(&c, argv))
if (!init(&c, envp)) exit_free(&c, EXIT_FAILURE);
exit(EXIT_FAILURE); if (c.script_fd)
shell_loop(&c); shell_script(&c, c.script_fd);
else if (!isatty(STDIN_FILENO))
shell_script(&c, STDIN_FILENO);
else
shell_loop(&c);
return (0); return (0);
} }

View File

@@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* error_wrappers.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/01 17:16:30 by lperrey #+# #+# */
/* Updated: 2021/12/16 04:38:05 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int shell_error(char *s1, char *s2, char *s3, int ret_val)
{
char *prefix;
prefix = "minishell: ";
write(STDERR_FILENO, prefix, ft_strlen(prefix));
if (s1)
write(STDERR_FILENO, s1, ft_strlen(s1));
if (s2)
write(STDERR_FILENO, s2, ft_strlen(s2));
if (s3)
write(STDERR_FILENO, s3, ft_strlen(s3));
write(STDERR_FILENO, "\n", 1);
return (ret_val);
}
int shell_perror(char *s1, char *s2, char *s3, int ret_val)
{
char *prefix;
prefix = "minishell: ";
write(STDERR_FILENO, prefix, ft_strlen(prefix));
if (s1)
write(STDERR_FILENO, s1, ft_strlen(s1));
if (s2)
write(STDERR_FILENO, s2, ft_strlen(s2));
if (s3)
write(STDERR_FILENO, s3, ft_strlen(s3));
perror(NULL);
return (ret_val);
}
int ft_reti_perror_io(int ret, char *err_str, char *io_file)
{
ft_putstr_fd(err_str, STDERR_FILENO);
perror(io_file);
return (ret);
}

98
srcs/misc/free.c Normal file
View File

@@ -0,0 +1,98 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* free.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
/* Updated: 2021/12/21 12:14:43 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int exit_free(t_all *c, int exit_status)
{
free(c->prompt_base);
free(c->prompt);
ft_lstclear((t_list **)&c->token_list, free);
ft_free_2d_arr(environ);
ft_free_2d_arr(c->path);
free_pipeline(&c->pipeline);
if (c->script_fd)
{
if (c->script_fd > 0)
{
gnl(c->script_fd, NULL, 1);
if (close(c->script_fd) == -1)
perror("close()");
}
}
else if (!isatty(STDIN_FILENO))
gnl(STDIN_FILENO, NULL, 1);
else
rl_clear_history();
close_stdio();
exit(exit_status);
}
void free_pipeline(t_cmd **pipeline_ptr[])
{
int i;
t_cmd **pipeline;
pipeline = *pipeline_ptr;
if (!pipeline)
return ;
close_pipeline_fd(pipeline);
i = 0;
while (pipeline[i])
{
ft_free_2d_arr(pipeline[i]->argv);
free(pipeline[i]->path);
i++;
}
ft_free_2d_arr(pipeline);
*pipeline_ptr = NULL;
}
void close_pipeline_fd(t_cmd *pipeline[])
{
int i;
if (!pipeline)
return ;
i = 0;
while (pipeline[i])
{
close_cmd_fd(pipeline[i]);
i++;
}
}
void close_cmd_fd(t_cmd *cmd)
{
if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0)
{
if (close(cmd->fd_in) == -1)
perror("close()");
cmd->fd_in = 0;
}
if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0)
{
if (close(cmd->fd_out) == -1)
perror("close()");
cmd->fd_out = 0;
}
}
void close_stdio(void)
{
if (close(STDIN_FILENO) == -1)
perror("close()");
if (close(STDOUT_FILENO) == -1)
perror("close()");
if (close(STDERR_FILENO) == -1)
perror("close()");
}

View File

@@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* last_exit_status.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/26 19:02:27 by lperrey #+# #+# */
/* Updated: 2021/12/20 16:48:02 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int set_last_exit_status(int new_value)
{
static int last_exit_status = 0;
if (new_value >= 0)
last_exit_status = new_value;
return (last_exit_status);
}
int get_last_exit_status(void)
{
return (set_last_exit_status(-1));
}

35
srcs/misc/retrieve_path.c Normal file
View File

@@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* retrieve_path.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:28:49 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
#define WARNING_PATH "Warning, $PATH not set\n"
int retrieve_path(char **path_stock[])
{
char *path;
char **path_split;
path = getenv("PATH");
if (!path)
{
ft_free_2d_arr(*path_stock);
*path_stock = NULL;
return (shell_error(WARNING_PATH, "", "", 0));
}
path_split = ft_split(path, ':');
if (!path_split)
return (ft_reti_perror(-1, "retrieve_path()"));
ft_free_2d_arr(*path_stock);
*path_stock = path_split;
return (1);
}

39
srcs/misc/signals.c Normal file
View File

@@ -0,0 +1,39 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* signals.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/23 18:56:53 by lperrey #+# #+# */
/* Updated: 2021/12/18 14:21:47 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void sigint_handler_interactive(int signum)
{
write(1, "\n", 1);
rl_on_new_line();
rl_replace_line("", 1);
rl_redisplay();
set_last_exit_status(EXIT_SIGNAL + signum);
}
void sigint_handler_heredoc(int signum)
{
(void)signum;
rl_done = 1;
g_switch_heredoc_sigint = 1;
}
void set_signals_behaviour(void)
{
struct sigaction signal_behaviour;
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGQUIT, &signal_behaviour, NULL);
sigaction(SIGINT, &signal_behaviour, NULL);
}

View File

@@ -1,81 +0,0 @@
#include "minishell.h"
void **cmd_path(char **argv, char **envp)
{
int i;
char **path;
char *cmd;
i = 0;
while (envp[i] && ft_strncmp(envp[i], "PATH=", 5))
i++;
path = ft_split(envp[i] + 5, ':'); // 5 = lentgh of "PATH="
i = -1;
while (*path && i != 0)
{
cmd = ft_strjoin(path[0], "/");
cmd = ft_strjoin(cmd, argv[0]);
i = access(cmd, X_OK);
path++;
}
argv[0] = cmd;
return (NULL);
}
int handle_fd(char **input, int i, int fdin, t_cmd *cmd)
{
int *pipes_fd;
int next_in;
char *tmp;
cmd->fd_in = fdin;
cmd->fd_out = 1;
cmd->fd_redirect = 1;
cmd->pipe_in = 0;
cmd->pipe_out = 1;
next_in = 0;
if (input[i + 1])
{
pipes_fd = calloc(2, sizeof(int));
pipe(pipes_fd);
cmd->fd_out = pipes_fd[1];
next_in = pipes_fd[0];
cmd->pipe_in = pipes_fd[0];
cmd->pipe_out = pipes_fd[1];
}
tmp = ft_strchr(input[i], '>');
if (tmp)
{
tmp[0] = '\0';
tmp = ft_strtrim(tmp + 2, " "); // +2 for "> "
cmd->fd_out = open(tmp, O_RDWR | O_TRUNC);
next_in = cmd->fd_out;
cmd->fd_redirect = cmd->fd_out;
}
return (next_in);
}
t_list *parser(char *input, char **envp)
{
t_list *cmd;
t_cmd *element;
char **input_split;
int i;
int tmp_fd;
input_split = ft_split(input, '|');
tmp_fd = 0;
i = 0;
cmd = NULL;
while (input_split[i])
{
element = calloc(1, sizeof(t_cmd));
tmp_fd = handle_fd(input_split, i, tmp_fd, element);
element->argv = ft_split(input_split[i], ' ');
element->builtin = cmd_path(element->argv, envp);
ft_lstadd_back(&cmd, ft_lstnew(element));
i++;
}
return (cmd);
}

View File

@@ -0,0 +1,95 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* create_pipeline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/02 22:46:23 by lperrey #+# #+# */
/* Updated: 2021/11/29 12:29:27 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static size_t cmd_words_count(t_token *t);
size_t count_pipes(t_token *t)
{
size_t count;
count = 0;
while (t)
{
if (t->id == T_PIPE)
count++;
t = t->next;
}
return (count);
}
t_cmd **pipeline_alloc(size_t cmd_nbr)
{
t_cmd **pipeline;
size_t i;
pipeline = ft_calloc(cmd_nbr + 1, sizeof (void *));
if (!pipeline)
return (ft_retp_perror(NULL, "pipeline_alloc()"));
i = 0;
while (i < cmd_nbr)
{
pipeline[i] = ft_calloc(1, sizeof (*pipeline[i]));
if (!pipeline[i])
{
ft_free_2d_arr(pipeline);
return (ft_retp_perror(NULL, "pipeline_alloc()"));
}
pipeline[i]->fd_in = STDIN_FILENO;
pipeline[i]->fd_out = STDOUT_FILENO;
i++;
}
return (pipeline);
}
int pipeline_fill_argv(t_token *t, t_cmd **pipeline)
{
size_t i;
size_t arg_i;
i = 0;
while (pipeline[i])
{
pipeline[i]->argv = ft_calloc(cmd_words_count(t) + 1, sizeof (char *));
if (!pipeline[i]->argv)
return (ft_reti_perror(0, "pipeline_fill_argv()"));
arg_i = 0;
while (t && t->id != '|')
{
if (t->id == T_WORD)
{
pipeline[i]->argv[arg_i++] = t->content;
t->content = NULL;
}
t = t->next;
}
if (t && t->id == '|')
t = t->next;
i++;
}
return (1);
}
static size_t cmd_words_count(t_token *t)
{
size_t count;
count = 0;
while (t && t->id != '|')
{
if (t->id == T_WORD)
count++;
t = t->next;
}
return (count);
}

View File

@@ -0,0 +1,52 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* content_copy.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/21 01:04:58 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static void quotes_handling(char c, int *quotes_state);
t_list *content_copy(char *content, int *i, int *quotes_state)
{
int i_exp;
t_list *expand;
expand = ft_lstnew_generic(sizeof(t_list), ft_strlen(&content[*i]) + 1);
if (!expand)
return (NULL);
i_exp = 0;
while (content[*i])
{
if (content[*i] == '$' && *quotes_state != IN_QUOTES)
break ;
quotes_handling(content[*i], quotes_state);
((char *)expand->content)[i_exp++] = content[(*i)++];
}
return (expand);
}
static void quotes_handling(char c, int *quotes_state)
{
if (c == '\'' && *quotes_state != IN_DQUOTES)
{
if (*quotes_state == IN_QUOTES)
*quotes_state = 0;
else
*quotes_state = IN_QUOTES;
}
else if (c == '\"' && *quotes_state != IN_QUOTES)
{
if (*quotes_state == IN_DQUOTES)
*quotes_state = 0;
else
*quotes_state = IN_DQUOTES;
}
}

View File

@@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* content_expand.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/21 01:20:40 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static char *env_var_expansion(char *content, int *i);
static char *retrieve_var(char *content, int *i);
t_list *content_expand(char *content, int *i)
{
t_list *expand;
expand = ft_lstnew(NULL);
if (!expand)
return (NULL);
expand->content = env_var_expansion(content, i);
if (!expand->content)
{
free(expand);
return (NULL);
}
return (expand);
}
static char *env_var_expansion(char *content, int *i)
{
char *expansion;
(*i)++;
if (content[*i] == '?')
{
(*i)++;
expansion = ft_itoa(get_last_exit_status());
}
else if (content[*i] == '_' || ft_isalpha(content[*i]))
expansion = retrieve_var(content, i);
else
{
expansion = ft_calloc(1 + 1, 1);
if (!expansion)
return (NULL);
expansion[0] = '$';
}
return (expansion);
}
static char *retrieve_var(char *content, int *i)
{
char *expansion;
char *tmp;
int i_exp;
expansion = ft_calloc(ft_strlen(&content[*i - 1]) + 1, 1);
if (!expansion)
return (NULL);
i_exp = 0;
while (content[*i] == '_' || ft_isalnum(content[*i]))
expansion[i_exp++] = content[(*i)++];
tmp = getenv(expansion);
ft_free_null(&expansion);
if (tmp)
expansion = ft_strdup(tmp);
else
expansion = ft_calloc(1, 1);
return (expansion);
}
/*
environment variables must be POSIX NAME :
3.235 Name
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
#tag_03_235
*/

View File

@@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* expand_token.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/21 01:12:42 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
t_list *content_copy(char *content, int *i, int *quotes_state);
t_list *content_expand(char *content, int *i);
t_list *expand_token(char *content)
{
int quotes_state;
int i;
t_list head;
t_list *expand;
head.next = NULL;
expand = &head;
quotes_state = 0;
i = 0;
while (content[i])
{
if (content[i] == '$')
expand->next = content_expand(content, &i);
else
expand->next = content_copy(content, &i, &quotes_state);
expand = expand->next;
if (!expand)
{
perror("expand_token() error");
return (ft_lstclear(&head.next, free));
}
}
return (head.next);
}

View File

@@ -0,0 +1,82 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* expansions.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/20 15:51:18 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
t_list *expand_token(char *content);
char *rejoin_after_expand(t_list *expand_lst);
int new_token_for_each_field(char **fields, t_token *t);
/*
* 1 - chaque bout dans un element d'une t_list
* (telle quelle si non expand, ou VARIABLE de env)
* 2 - strjoin() le tout
* 3 - split avec un ft_strplit() modifié (ne splitant pas dans les quotes)
* 4 - quotes removal, ft_strdup_quotes() le tableau split
* 5 - creer un token T_WORD pour chaque *string du **split_arr
* (ft_lstadd_front() sur le token original, puis set le token orignal à :
* t->id = 0 ;
* free(t->content) ;
* t->content = NULL ;
* pour qu'il soit ignoré sur la suite du parsing)
*/
int expansions(t_token *t, t_cmd **pipeline)
{
int i;
t_token *next_token;
i = 0;
while (t)
{
if (t->id == '|')
i++;
if (!pipeline[i]->error && t->id == T_WORD)
{
next_token = t->next;
if (!token_expansions(t))
{
pipeline[i]->error = EXIT_EXPANSION;
}
while (t != next_token)
t = t->next;
}
else
t = t->next;
}
return (1);
}
int token_expansions(t_token *t)
{
void *tmp;
char **tmp_split;
tmp = (t_list *)expand_token(t->content);
if (!tmp)
return (0);
tmp = (char *)rejoin_after_expand(tmp);
if (!tmp)
return (0);
tmp_split = ft_split_quotes(tmp, ' ');
free(tmp);
if (!tmp_split)
return (0);
tmp = tmp_split;
tmp_split = ft_dup_2d_arr(tmp_split, (t_dup_f)ft_strdup_quotes);
ft_free_2d_arr(tmp);
if (!tmp_split)
return (0);
if (!new_token_for_each_field(tmp_split, t))
return (0);
return (1);
}

View File

@@ -0,0 +1,59 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* new_token_for_each_field.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/20 17:22:41 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static void insert_tokens(t_token *t, t_token *insert_lst);
int new_token_for_each_field(char **fields, t_token *t)
{
t_token head;
t_token *insert_lst;
int i;
head.next = NULL;
insert_lst = &head;
i = 0;
while (fields[i])
{
insert_lst->next = ft_lstnew_generic(sizeof(t_token), 0);
insert_lst = insert_lst->next;
if (!insert_lst)
{
perror("insert_token_for_each_field() error");
ft_free_2d_arr(fields);
ft_lstclear((t_list **)&head.next, NULL);
return (0);
}
insert_lst->content = fields[i];
insert_lst->id = T_WORD;
i++;
}
free(fields);
insert_tokens(t, head.next);
return (1);
}
static void insert_tokens(t_token *t, t_token *insert_lst)
{
t_token *tmp;
t_token *insert_lst_last;
t->id = 0;
ft_free_null(&t->content);
if (!insert_lst)
return ;
tmp = t->next;
t->next = insert_lst;
insert_lst_last = (t_token *)ft_lstlast((t_list *)insert_lst);
insert_lst_last->next = tmp;
}

View File

@@ -0,0 +1,34 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* rejoin_after_expand.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/20 14:55:03 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
char *rejoin_after_expand(t_list *expand_lst)
{
t_list *head;
char *result;
head = expand_lst;
result = NULL;
while (expand_lst)
{
result = ft_strjoinfree_s1(result, expand_lst->content);
if (!result)
{
perror("rejoin_after_expand() error");
return (ft_lstclear(&head, free));
}
expand_lst = expand_lst->next;
}
ft_lstclear(&head, free);
return (result);
}

115
srcs/parsing/parsing.c Normal file
View File

@@ -0,0 +1,115 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parsing.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */
/* Updated: 2021/12/22 13:53:19 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void save_redirections_words(t_token *t);
t_cmd **parsing(t_token *token_list, int script_fd)
{
t_cmd **pipeline;
if (!valid_syntax(token_list))
return (NULL);
save_redirections_words(token_list);
pipeline = pipeline_alloc(1 + count_pipes(token_list));
if (!pipeline)
return (NULL);
if (!expansions(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
if (!redirections(token_list, pipeline, script_fd))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
if (!pipeline_fill_argv(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
return (pipeline);
}
void save_redirections_words(t_token *t)
{
while (t)
{
if (t->id == '>' || t->id == T_DGREAT
|| t->id == '<' || t->id == T_DLESS)
{
t = t->next;
t->id = T_REDIRECTION_WORD;
}
t = t->next;
}
}
/*
2.9.1 Simple Commands
2.9.1 - 1) Save Words
2.9.1 - 2) Expansion
2.9.1 - 3) Redirection
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
#tag_18_09_01
*/
/*
2.10 Shell Grammar
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
#tag_18_10
*/
/* -------------------------------------------------------
The grammar symbols
------------------------------------------------------- */
/*
%token WORD
%token LESS // '<'
%token GREAT // '>'
%token DLESS // '<<'
%token DGREAT // '>>'
%token PIPE // '|'
*/
/* -------------------------------------------------------
The Simplified Grammar
------------------------------------------------------- */
/*
%start program
%%
pipeline : command
| pipeline '|' command
;
command : cmd_prefix cmd_name cmd_suffix
| cmd_prefix cmd_name
| cmd_name cmd_suffix
| cmd_name
| cmd_prefix
;
cmd_name : WORD // Apply rule 7a
;
cmd_prefix : io_redirect
| cmd_prefix io_redirect
;
cmd_suffix : io_redirect
| cmd_suffix io_redirect
| WORD
| cmd_suffix WORD
;
io_redirect : io_file
| io_here
;
io_file : '<' filename
| '>' filename
| DGREAT filename
;
filename : WORD // Apply rule 2
;
io_here : DLESS here_end
;
here_end : WORD // Apply rule 3
;
*/

View File

@@ -0,0 +1,165 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* here_doc.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/12/22 17:04:47 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int here_doc_write(char *delimiter, int doc_fd, int script_fd);
static int here_doc_write_interactive(char *delimiter, int doc_fd);
static int here_doc_write_script(char *delimiter, int doc_fd, int script_fd);
static int event_hook_empty(void);
#define TMP_HERE_DOC "/tmp/minishell_here_doc"
#define WARNING_EOF "warning: here-document delimited by end-of-file (wanted `"
int here_doc(char *delimiter, int script_fd)
{
int here_doc;
int ret;
delimiter = ft_strdup_quotes(delimiter);
if (!delimiter)
return (ft_reti_perror(-1, "ft_strdup_quotes()"));
here_doc = open(TMP_HERE_DOC, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (here_doc == -1)
return (ft_reti_perror_io(-1, "open() ", TMP_HERE_DOC));
ret = here_doc_write(delimiter, here_doc, script_fd);
free(delimiter);
if (close(here_doc) == -1)
shell_perror(TMP_HERE_DOC, ": ", "", 0);
if (ret != 0)
{
if (unlink(TMP_HERE_DOC) == -1)
return (ft_reti_perror_io(ret, "unlink() ", TMP_HERE_DOC));
return (ret);
}
here_doc = open(TMP_HERE_DOC, O_RDONLY);
if (here_doc == -1)
shell_perror(TMP_HERE_DOC, ": ", "", 0);
if (unlink(TMP_HERE_DOC) == -1)
return (ft_reti_perror_io(-1, "unlink() ", TMP_HERE_DOC));
return (here_doc);
}
static int here_doc_write(char *delimiter, int doc_fd, int script_fd)
{
int ret;
struct sigaction signal_action;
if (script_fd || !isatty(STDIN_FILENO))
{
ret = here_doc_write_script(delimiter, doc_fd, script_fd);
}
else
{
ft_bzero(&signal_action, sizeof(signal_action));
signal_action.sa_handler = sigint_handler_heredoc;
sigaction(SIGINT, &signal_action, NULL);
rl_event_hook = event_hook_empty;
ret = here_doc_write_interactive(delimiter, doc_fd);
rl_event_hook = NULL;
signal_action.sa_handler = SIG_IGN;
sigaction(SIGINT, &signal_action, NULL);
}
return (ret);
}
static int here_doc_write_interactive(char *delimiter, int doc_fd)
{
char *line;
size_t line_len;
line = NULL;
g_switch_heredoc_sigint = 0;
while (1)
{
line = readline("> ");
if (g_switch_heredoc_sigint == 1)
return (set_last_exit_status(EXIT_SIGNAL + SIGINT));
if (!line)
return (shell_error(WARNING_EOF, delimiter, "')", 0));
line_len = ft_strlen(line);
if (ft_strncmp(line, delimiter, line_len + 1) == 0)
break ;
if (write(doc_fd, line, line_len) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
if (write(doc_fd, "\n", 1) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
ft_free_null(&line);
}
free(line);
return (0);
}
static int here_doc_write_script(char *delimiter, int doc_fd, int script_fd)
{
char *line;
int ret;
size_t line_len;
line = NULL;
ret = 1;
while (ret)
{
ret = gnl(script_fd, &line, 0);
if (ret == -1)
return (ft_reti_perror_free(-1, line, free, "gnl() script_fd"));
line_len = ft_strlen(line);
if (ft_strncmp(line, delimiter, line_len + 1) == 0)
break ;
if (write(doc_fd, line, line_len) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
if ((ret || line[0]) && write(doc_fd, "\n", 1) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
ft_free_null(&line);
}
if (!line && ret == 0)
shell_error(WARNING_EOF, delimiter, "')", 0);
free(line);
return (0);
}
static int event_hook_empty(void)
{
return (0);
}
/*
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
#tag_18_07_04
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
#tag_18_02
*/
/* If any part of word is quoted,
the delimiter shall be formed by performing quote removal on word,
and the here-document lines shall not be expanded.
Otherwise, the delimiter shall be the word itself. */
// TODO Bonus: expansions in here_doc.
/*
** rl_done
** Setting this to a non-zero value causes Readline
** to return the current line immediately.
** rl_event_hook
** If non-zero, this is the address of a function to call periodically
** when Readline is waiting for terminal input.
** By default, this will be called at most
** ten times a second if there is no keyboard input.
**
** https://stackoverflow.com/questions/53165704/
** readline-c-force-return-of-certain-text-in-readline
** "rl_done is only checked in the event loop. When you give it
** a null event hook function, it checks the rl_done and exits"
**
** rl_signal_event_hook
** If non-zero, this is the address of a function to call if a read
** system call is interrupted when Readline is reading terminal input.
*/

View File

@@ -0,0 +1,138 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* redirections.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/12/22 14:00:33 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int here_doc(char *delimiter, int script_fd);
static int redirect_cmd_input(t_token *t, t_cmd *cmd);
static int redirect_cmd_heredoc(t_token *t, t_cmd *cmd, int script_fd);
static int redirect_cmd_output(t_token *t, t_cmd *cmd);
static int expand_redirection(t_token *t);
int redirections(t_token *t, t_cmd **pipeline, int script_fd)
{
int i;
i = 0;
while (t)
{
if (t->id == '|')
i++;
if (!pipeline[i]->error)
{
if (t->id == '<' && !redirect_cmd_input(t, pipeline[i]))
return (0);
else if (t->id == T_DLESS
&& !redirect_cmd_heredoc(t, pipeline[i], script_fd))
return (0);
else if (t->id == '>' || t->id == T_DGREAT)
if (!redirect_cmd_output(t, pipeline[i]))
return (0);
}
t = t->next;
}
return (1);
}
static int redirect_cmd_input(t_token *t, t_cmd *cmd)
{
if (cmd->fd_in != STDIN_FILENO)
if (close(cmd->fd_in) == -1)
perror("close()");
if (!expand_redirection(t))
{
cmd->error = EXIT_REDIRECTION;
return (1);
}
cmd->fd_in = open(t->next->content, O_RDONLY);
if (cmd->fd_in == -1)
{
shell_perror(t->next->content, ": ", "", 0);
cmd->error = EXIT_REDIRECTION;
}
return (1);
}
static int redirect_cmd_heredoc(t_token *t, t_cmd *cmd, int script_fd)
{
if (cmd->fd_in != STDIN_FILENO)
if (close(cmd->fd_in) == -1)
perror("close()");
cmd->fd_in = here_doc(t->next->content, script_fd);
if (cmd->fd_in == -1)
{
shell_error("heredoc error", ": ", "", 0);
cmd->error = EXIT_REDIRECTION;
}
else if (cmd->fd_in > EXIT_SIGNAL)
{
cmd->fd_in = 0;
return (0);
}
return (1);
}
static int redirect_cmd_output(t_token *t, t_cmd *cmd)
{
int flags;
if (cmd->fd_out != STDOUT_FILENO)
if (close(cmd->fd_out) == -1)
perror("close()");
if (!expand_redirection(t))
{
cmd->error = EXIT_REDIRECTION;
return (1);
}
flags = O_WRONLY | O_CREAT;
if (t->id == '>')
flags = flags | O_TRUNC;
else if (t->id == T_DGREAT)
flags = flags | O_APPEND;
cmd->fd_out = open(t->next->content, flags, S_IRWXU);
if (cmd->fd_out == -1)
{
shell_perror(t->next->content, ": ", "", EXIT_REDIRECTION);
cmd->error = EXIT_REDIRECTION;
}
return (1);
}
static int expand_redirection(t_token *t)
{
t_token *head;
t_token *next_token;
int ret;
ret = 1;
head = t;
t = t->next;
next_token = t->next;
t->next = NULL;
if (!token_expansions(t))
{
((t_token *)ft_lstlast((t_list *)head))->next = next_token;
return (0);
}
head->next = t->next;
free(t);
if (head->next)
head->next->id = T_REDIRECTION_WORD;
if (ft_lstsize((t_list *)head->next) != 1)
{
ret = 0;
shell_error("", "", "ambiguous redirect", 0);
}
((t_token *)ft_lstlast((t_list *)head))->next = next_token;
return (ret);
}

View File

@@ -0,0 +1,83 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* rules_command.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */
/* Updated: 2021/12/22 22:11:40 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int valid_io_redirect(t_token **token_list);
// cmd_prefix cmd_name cmd_suffix
int valid_command_rule1(t_token **token_list)
{
if (!valid_io_redirect(token_list))
return (0);
while (valid_io_redirect(token_list))
continue ;
if (!valid_token(token_list, T_WORD))
return (0);
if (!valid_token(token_list, T_WORD) && !valid_io_redirect(token_list))
return (0);
while (valid_token(token_list, T_WORD) || valid_io_redirect(token_list))
continue ;
if (!valid_command_separator(*token_list))
return (0);
return (1);
}
// cmd_prefix cmd_name
int valid_command_rule2(t_token **token_list)
{
if (!valid_io_redirect(token_list))
return (0);
while (valid_io_redirect(token_list))
continue ;
if (!valid_token(token_list, T_WORD))
return (0);
if (!valid_command_separator(*token_list))
return (0);
return (1);
}
// cmd_name cmd_suffix
int valid_command_rule3(t_token **token_list)
{
if (!valid_token(token_list, T_WORD))
return (0);
if (!valid_token(token_list, T_WORD) && !valid_io_redirect(token_list))
return (0);
while (valid_token(token_list, T_WORD) || valid_io_redirect(token_list))
continue ;
if (!valid_command_separator(*token_list))
return (0);
return (1);
}
// cmd_name
int valid_command_rule4(t_token **token_list)
{
if (!valid_token(token_list, T_WORD))
return (0);
if (!valid_command_separator(*token_list))
return (0);
return (1);
}
// cmd_prefix
int valid_command_rule5(t_token **token_list)
{
if (!valid_io_redirect(token_list))
return (0);
while (valid_io_redirect(token_list))
continue ;
if (!valid_command_separator(*token_list))
return (0);
return (1);
}

View File

@@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* valid_command.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */
/* Updated: 2021/12/22 20:19:08 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int valid_command_rule1(t_token **token_list);
int valid_command_rule2(t_token **token_list);
int valid_command_rule3(t_token **token_list);
int valid_command_rule4(t_token **token_list);
int valid_command_rule5(t_token **token_list);
int valid_command(t_token **token_list)
{
t_token *cmd_start;
cmd_start = *token_list;
if (valid_command_rule1(token_list))
return (1);
*token_list = cmd_start;
if (valid_command_rule2(token_list))
return (1);
*token_list = cmd_start;
if (valid_command_rule3(token_list))
return (1);
*token_list = cmd_start;
if (valid_command_rule4(token_list))
return (1);
*token_list = cmd_start;
if (valid_command_rule5(token_list))
return (1);
*token_list = cmd_start;
return (0);
}

View File

@@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* valid_io_redirect.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:52:42 by lperrey #+# #+# */
/* Updated: 2021/10/24 19:21:35 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int valid_io_file(t_token **token_list);
static int valid_io_here(t_token **token_list);
int valid_io_redirect(t_token **token_list)
{
if (valid_io_file(token_list) || valid_io_here(token_list))
return (1);
return (0);
}
static int valid_io_file(t_token **token_list)
{
if (valid_token(token_list, '<') || valid_token(token_list, '>')
|| valid_token(token_list, T_DGREAT))
{
if (valid_token(token_list, T_WORD))
return (1);
}
return (0);
}
static int valid_io_here(t_token **token_list)
{
if (valid_token(token_list, T_DLESS))
{
if (valid_token(token_list, T_WORD))
return (1);
}
return (0);
}

View File

@@ -0,0 +1,28 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* valid_pipeline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:51:35 by lperrey #+# #+# */
/* Updated: 2021/10/24 19:35:16 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int valid_command(t_token **token_list);
int valid_pipeline(t_token **token_list)
{
while (valid_command(token_list))
{
if (*token_list == NULL)
return (1);
else if ((*token_list)->id != '|' || (*token_list)->next == NULL)
return (0);
valid_token(token_list, '|');
}
return (0);
}

View File

@@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* valid_syntax.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 13:01:10 by lperrey #+# #+# */
/* Updated: 2021/10/24 19:40:23 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int valid_pipeline(t_token **token_list);
int valid_syntax(t_token *token_list)
{
if (valid_pipeline(&token_list))
return (1);
else
{
ft_putstr_fd("minishell: syntax error near unexpected token \'", 2);
ft_putstr_fd(token_list->content, 2);
ft_putstr_fd("\'\n", 2);
}
return (0);
}
int valid_token(t_token **token_list, enum e_token_id token_id)
{
if (*token_list != NULL && (*token_list)->id == token_id)
{
*token_list = (*token_list)->next;
return (1);
}
return (0);
}
int valid_command_separator(const t_token *token_list)
{
if (token_list == NULL || token_list->id == '|')
return (1);
return (0);
}

View File

@@ -1,53 +0,0 @@
#include "minishell.h"
int size_tab(char **split)
{
int i;
i = 0;
while (*split++)
i++;
return (i);
}
void print_tab(char **array)
{
int i;
i = 0;
while (array[i])
{
printf("%i: [%s]\n", i, array[i]);
i++;
}
}
void cmd_execution(char *cmd, t_all *c)
{
const char *filename;
char **argv;
char **envp;
// (void)cmd;
filename = ft_strtrim(cmd, " ");
printf("[%s]\n", filename);
// filename = "/bin/ls";
argv = ft_split(filename, ' ');
envp = c->envp;
execve(filename, argv, envp);
}
void pipes_hugo(char *input, t_all *c)
{
char **split;
int nbr_pipes;
int i;
split = ft_split(input, '|');
split[0] += 5; // pour sauter la premiere entree qui est "pipe"
nbr_pipes = size_tab(split);
//printf("%i\n", nbr_pipes);
//print_tab(split);
i = 0;
cmd_execution(split[i], c);
}

60
srcs/shell_loop.c Normal file
View File

@@ -0,0 +1,60 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* shell_loop.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
/* Updated: 2021/12/22 13:56:38 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static char *read_input(char *prompt, t_all *c);
void shell_loop(t_all *c)
{
char *line_input;
line_input = NULL;
while (1)
{
free(line_input);
line_input = read_input(c->prompt, c);
if (line_input && *line_input)
{
add_history(line_input);
c->token_list = lexing(line_input);
ft_free_null(&line_input);
if (!c->token_list)
continue ;
c->pipeline = parsing(c->token_list, 0);
ft_lstclear((t_list **)&c->token_list, free);
if (!c->pipeline)
continue ;
exec_cmd_line(c);
}
}
}
static char *read_input(char *prompt, t_all *c)
{
char *line_input;
struct sigaction signal_behaviour;
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
signal_behaviour.sa_handler = sigint_handler_interactive;
sigaction(SIGINT, &signal_behaviour, NULL);
rl_event_hook = NULL;
line_input = readline(prompt);
signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGINT, &signal_behaviour, NULL);
if (!line_input)
{
write(STDERR_FILENO, "exit\n", 5);
exit_free(c, get_last_exit_status());
}
return (line_input);
}

75
srcs/shell_script.c Normal file
View File

@@ -0,0 +1,75 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* shell_script.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/26 23:47:44 by lperrey #+# #+# */
/* Updated: 2021/12/22 14:01:52 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static char *read_input_script(t_all *c, int script_fd);
static void exit_signal(t_all *c);
void shell_script(t_all *c, int script_fd)
{
char *line_input;
line_input = NULL;
while (1)
{
free(line_input);
line_input = read_input_script(c, script_fd);
if (!line_input)
break ;
if (line_input && *line_input)
{
c->token_list = lexing(line_input);
ft_free_null(&line_input);
if (!c->token_list)
break ;
c->pipeline = parsing(c->token_list, script_fd);
ft_lstclear((t_list **)&c->token_list, free);
if (!c->pipeline)
break ;
exec_cmd_line(c);
if (get_last_exit_status() > EXIT_SIGNAL)
exit_signal(c);
}
}
exit_free(c, get_last_exit_status());
}
static char *read_input_script(t_all *c, int script_fd)
{
char *line_input;
struct sigaction signal_behaviour;
int ret;
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGINT, &signal_behaviour, NULL);
line_input = NULL;
ret = gnl(script_fd, &line_input, 0);
if (ret == -1)
{
free(line_input);
return (NULL);
}
if (!line_input[0] && ret == 0)
{
free(line_input);
exit_free(c, get_last_exit_status());
}
return (line_input);
}
static void exit_signal(t_all *c)
{
write(STDOUT_FILENO, "\n", 1);
exit_free(c, get_last_exit_status());
}

View File

17
tests/env_var_test.c Normal file
View File

@@ -0,0 +1,17 @@
# include <stdio.h>
# include <stdlib.h>
int main(int argc, char *argv[], char *envp[])
{
int i;
printf("argc = %i\n", argc);
i = 0;
while (argv[i])
{
printf("%s = |%s|\n", argv[i], getenv(argv[i]));
i++;
}
return (0);
}

17
tests/test_segfault.c Normal file
View File

@@ -0,0 +1,17 @@
# include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[], char *envp[])
{
int i;
char *str;
str = NULL;
i = 0;
while (str[i])
{
write(1, &str[i], 1);
}
return (0);
}

7
tests/trop_de_pipes.sh Normal file

File diff suppressed because one or more lines are too long

View File

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