140 Commits
Author SHA1 Message Date
hugogogo b81ea045e8 ajout qq sources dans readme 2021-12-20 12:26:39 +01:00
hugogogo 0272d3a26f merge conflicts 2021-12-19 12:12:43 +01:00
hugogogo 5edae3c86a modifs in minishell_tests et unset 2021-12-19 10:52:48 +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
hugogogo 7dcf48dd78 merge de luke 2021-12-18 12:34:26 +01:00
hugogogo 01bbec2774 modifs avec luke 2021-12-18 12:30:12 +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
hugogogo 8d6d5514d8 a jour avec la branche master 2021-12-17 17:48:22 +01:00
hugogogo 530027c0e8 commit pour merge 2021-12-17 12:00:32 +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
hugogogo 424e2563ac commit change in readme 2021-12-16 14:45:42 +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
hugogogo 101646f644 modifs readme 2021-12-15 14:05:24 +01:00
hugogogo 3490b2ac8f modifs en cours dans readme 2021-12-15 14:03:52 +01:00
hugogogo ef490c011e modifs en cours dans readme 2021-12-15 13:45:16 +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
hugogogo 48a3abac15 modifs dans submodule minishell_test 2021-12-10 19:32:14 +01:00
hugogogo 05003b8a91 merge conflicts 2021-12-10 10:29:45 +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
hugogogo a485b3046e ajouts des tests discord 2021-12-05 18:26:44 +01:00
LuckyLaszlo b7b3cec6e0 builtin unset + fixed builtin export 2021-12-05 18:15:23 +01:00
hugogogo 39908b71d9 debug du heredoc en pipeline finalement la cause est rldone 2021-12-05 17:44:26 +01:00
LuckyLaszlo 66183ab441 cd refactoring, error_wrappers 2021-12-05 16:28:41 +01:00
hugogogo 10a8ecaae8 recherche du pbm dans heredoc 2021-12-05 14:16:11 +01:00
hugogogo 0171de26e9 debug de heredoc 2021-12-05 11:08:49 +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
hugogogo a288ad473e test unitaires a peu pres ok :) 2021-12-03 22:32:07 +01:00
LuckyLaszlo 2eed0f2d45 little fix, ft_lstnew_generic() prototype.
+ unused c var in builtin_env()
2021-12-03 16:10:04 +01:00
hugogogo 27f8059d8a fix bug last line et ajout info sur next command si option print 2021-12-03 12:24:23 +01:00
hugogogo 6ac25b11ae ajout option log et ignore comments in tests 2021-12-03 11:22:24 +01:00
hugogogo 294a818924 tests heredocs 2021-12-03 07:01:20 +01:00
hugogogo 687b1d8631 tests heredocs 2021-12-03 07:00:39 +01:00
hugogogo a432f6bf77 qq modifs pour pouvoir travailler sur les tests 2021-12-02 15:56:59 +01:00
hugogogo bb73a5e65c resolve merge conflict small changes in heredoc 2021-12-02 15:33:42 +01:00
hugogogo 116276b0a2 test unitaire avance 2021-12-02 15:29:16 +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
hugogogo 6a077174bc debut ecriture test_unitaires var assign resultat de plusieurs commandes 2021-11-30 22:34:34 +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
72 changed files with 3680 additions and 597 deletions
+6 -1
View File
@@ -1,4 +1,5 @@
.DS_Store
Thumbs.db
*.o
*.swp
*.out
@@ -9,7 +10,11 @@
*.dSYM
.vscode
*.lnk
*.zip
memo
memo.txt
minishell
*.zip
arg_test
osef_temp
env_var_test
memo_local
+3
View File
@@ -1,3 +1,6 @@
[submodule "libft"]
path = libft
url = git@bitbucket.org:LuckyLaszlo/libft.git
[submodule "minishell_tests"]
path = minishell_tests
url = git@bitbucket.org:LuckyLaszlo/minishell_tests.git
+27 -4
View File
@@ -2,10 +2,18 @@ NAME = minishell
CC = clang
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -g
CFLAGS = -Wall -Wextra $(INCLUDES) -g # add -Werror, del -g
VPATH = $(DIR_SRCS)
DIR_SRCS = srcs srcs/builtins
DIR_SRCS = srcs \
srcs/init \
srcs/builtins \
srcs/lexing \
srcs/parsing srcs/parsing/valid_syntax \
srcs/parsing/expansions srcs/parsing/redirections \
srcs/exec \
srcs/generic \
srcs/misc \
INCLUDES = -I$(HEADERS_D) -I$(LIBFT_D)
@@ -21,8 +29,23 @@ LIBS = -L $(LIBFT_D) -lft \
LIBFT_D = ./libft
LIBFT = $(LIBFT_D)/libft.a
SRCS = main.c init.c free.c generic.c \
env.c exit.c
SRCS = main.c \
shell_loop.c shell_script.c \
init.c init_prompt.c init_readline.c init_shlvl.c handle_argv.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 rejoin_after_expand.c new_token_for_each_field.c \
redirections.c here_doc.c \
exec_cmd_line.c pipeline.c \
find_access.c subshell_exec.c subshell_wait.c simple_cmd_builtin.c \
cd.c pwd.c export.c unset.c exit.c env.c echo.c \
ft_split_quotes.c ft_strdup_quotes.c \
ft_strjoinfree.c ft_lst_func.c ft_isinset_str.c ft_is_posix_name.c \
ft_getenv.c ft_free_null.c ft_2d_arr_func.c \
DIR_OBJS = builds
OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o)
+136 -460
View File
@@ -1,488 +1,164 @@
## 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 :
## todo list :
---
- **global features :**
- `prompt` *show a prompt*
- `history` **? the command history ?**
- `history` *use history with arrows*
- `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)
- `'` `"` `;` `\` *don't interpret special characters and unclosed quotes*
- **pipes :** [video on pipes](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/)
- `$?` *exit return of last executed process* [meaning-of $?](https://stackoverflow.com/questions/7248031/meaning-of-dollar-question-mark-in-shell-scripts)
- **quotes :** [quotes in bash](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/)
- **redirections & heredocs :** [redirections](https://www.gnu.org/software/bash/manual/html_node/Redirections.html) / [heredocs](https://www.techrepublic.com/article/use-heredoc-in-shell-scripts/)
- `<` *redirect input*
- `>` *redirect output*
- `<<` *read input until empty line --* **? doesn't update history ?**
- `<<` *read input until empty line --*
- `>>` *redirect and append*
- **signals :**
- `^C` *close process*
- `^D` *exit minishell*
- `^\` *do nothing*
- **builtins (can't be executed in child process) :**
- **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)
- `exit`
- **builtins :** (but they don't need to be)
- `env`
- ~~`echo`~~
- `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. parsing :
## allowed external functions :
---
### 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
ARCHITECTURE :
all
expend $
. pipes
. . redirections (program function or file)
. . . arguments (nom arg arg arg ...)
. . . .
EXEMPLE : . .
[sort < ./prgrm 'arg1 '$VARIABLE" arg3" | grep "word.$EXTENSION" | wc -l > file]
[sort < ./prgrm 'arg1 'arg2" arg3" | grep "word.md" | wc -l > file]
. [sort < ./prgrm 'arg1 'arg2" arg3"]
. . [sort]
. . [./prgrm 'arg1 'arg2" arg3"]
. . . [./prgrm]
. . . ['arg1 ']
. . . [arg2]
. . . [" arg3"]
. [grep "word.md"]
. . . [grep]
. . . ["word.md"]
. [wc -l > file]
. . [wc -l]
. . . [wc]
. . . [-l]
. . [file]
```
*[\go to sommaire](#markdown-header-sommaire)*
## 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 :
---
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)*
(extracts of manuals)
**readline :**
- **readline** : `char *readline (const char *prompt);` will read a line from the terminal and return it, using prompt as a prompt
- **rl_clear_history** : `void rl_clear_history (void)` clear the history list by deleting all of the entries, in the same manner as the History library's clear_history() function
- **rl_on_new_line** : `int rl_on_new_line (void)` tell the update functions that we have moved onto a new (empty) line, usually after outputting a newline
- **rl_replace_line** : `void rl_replace_line (const char *text, int clear_undo)` replace the contents of rl_line_buffer with text. The point and mark are preserved, if possible. If clear_undo is non-zero, the undo list associated with the current line is cleared
- **rl_redisplay** : `void rl_redisplay (void)` change what's displayed on the screen to reflect the current contents of rl_line_buffer
- **add_history** : `bool readline_add_history (string $prompt)` save the line away in a history list of such lines
**files :**
- **access** : `int access(const char *pathname, int mode);` checks whether the calling process can access the file pathname
- **open** : `int open(const char *pathname, int flags, [mode_t mode]);` system call opens the file specified by pathname
- **read** : `ssize_t read(int fd, void *buf, size_t count);` attempts to read up to count bytes from file descriptor fd into the buffer starting at buf
- **close** : `int close(int fd);` closes a file descriptor, so that it no longer refers to any file and may be reused
- **dup** : `int dup(int oldfd);` creates a copy of the file descriptor oldfd, using the lowest-numbered unused file descriptor for the new descriptor
- **dup2** : `int dup2(int oldfd, int newfd);` performs the same task as dup(), but instead of using the lowest-numbered unused file descriptor, it uses the file descriptor number specified in newfd
- **pipe** : `int pipe(int pipefd[2]);` creates a pipe, a unidirectional data channel that can be used for interprocess communication. The array pipefd is used to return two file descriptors referring to the ends of the pipe. pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe
- **stat** : `int stat(const char *pathname, struct stat *statbuf);` returns information about a file, in the buffer pointed to by statbuf
- **lstat** : `int fstat(int fd, struct stat *statbuf);` lstat() is identical to stat(), except that if pathname is a symbolic link, then it returns information about the link itself, not the file that it refers to
- **fstat** : `int lstat(const char *pathname, struct stat *statbuf);` fstat() is identical to stat(), except that the file about which information is to be retrieved is specified by the file descriptor fd
- **unlink** : `int unlink(const char *pathname);` unlink() deletes a name from the filesystem
**process :**
- **fork** : `pid_t fork(void);` creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process
- **wait** : `pid_t wait(int *wstatus);` suspends execution of the calling process until one of its children terminates. The call wait(&wstatus) is equivalent to: waitpid(-1, &wstatus, 0);
- **waitpid** : `pid_t waitpid(pid_t pid, int *wstatus, int options);` suspends execution of the calling process until a child specified by pid argument has changed state
- **wait3** : `pid_t wait3(int *wstatus, int options, struct rusage *rusage);` obsolete; use waitpid(2). similar to waitpid(2), but additionally return resource usage information about the child in the structure pointed to by rusage
- **wait4** : `pid_t wait4(pid_t pid, int *wstatus, int options, struct rusage *rusage);` like wait3() but additionally can be used to select a specific child
- **exit** : `void exit(int status);` causes normal process termination and the value of status & 0377 is returned to the parent (see wait())
**signals :**
- **signal** : `sighandler_t signal(int signum, sighandler_t handler(int));` sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer-defined function (a "signal handler")
- **sigaction** : `int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);` change the action taken by a process on receipt of a specific signal.
- **kill** : `int kill(pid_t pid, int sig);` send any signal to any process group or process
**directories :**
- **getcwd** : `char *getcwd(char *buf, size_t size);` returns a null-terminated string containing an absolute pathname that is the current working directory of the calling process
- **chdir** : `int chdir(const char *path);` changes the current working directory of the calling process to the directory specified in path
- **execve** : `int execve(const char *filename, char *const argv[], char *const envp[]);` executes the program pointed to by filename
- **opendir** : `DIR *opendir(const char *name);` opens a directory stream corresponding to the directory name, and returns a pointer to the directory stream
- **readdir** : `struct dirent *readdir(DIR *dirp);` returns a pointer to a dirent structure representing the next directory entry in the directory stream pointed to by dirp
- **closedir** : `int closedir(DIR *dirp);` closes the directory stream associated with dirp
**errors :**
- **strerror** : `char *strerror(int errnum);` returns a pointer to a string that describes the error code passed in the argument errnum
- **perror** : `void perror(const char *s);` produces a message on standard error describing the last error encountered during a call to a system or library function
**termcap :**
The termcap data base describes the capabilities of hundreds of different display terminals in great detail
The termcap library is provided for easy access this data base in programs that want to do terminal-independent character-based display output
- **tgetent** : `int tgetent (char *buffer, char *termtype);` finds the description of the terminal type and remembers it internally so that you can interrogate it about specific terminal capabilities
Each piece of information recorded in a terminal description is called a capability
There are three functions to use to get the value of a capability :
- **tgetflag** : `int tgetflag (char *name);` get a boolean value
- **tgetnum** : `int tgetnum (char *name);` get a capability value that is numeric
- **tgetstr** : `char *tgetstr (char *name, char **area);` get a string value
two more functions :
- **tgoto** : `char *tgoto (char *cstring, int hpos, int vpos)` encoding numeric parameters such as cursor positions into the terminal-specific form required for display commands
- **tputs** : `int tputs (char *string, int nlines, int (*outfun) ());` output a string containing an optional padding spec
**other :**
- **printf** : `int printf(const char *format, ...);` produce output to stdout according to a specified format
- **malloc** : `void *malloc(size_t size);` allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized
- **free** : `void free(void *ptr);` frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc()
- **write** : `ssize_t write(int fd, const void *buf, size_t count);` writes up to <count> bytes from the buffer starting at <buf> to the file referred to by the file descriptor <fd>
- **isatty** : `int isatty(int fd);` tests whether fd is an open file descriptor referring to a terminal
- **ttyname** : `char *ttyname(int fd);` returns a pointer to the null-terminated pathname of the terminal device that is open on the file descriptor fd, or NULL on error (for example, if fd is not connected to a terminal)
- **ttyslot** : `int ttyslot(void);` returns the index of the current user's entry in some file
- **ioctl** : `int ioctl(int fd, unsigned long request, ...);` manipulates the underlying device parameters of special files. In particular, many operating characteristics of character special files (e.g., terminals) may be controlled with ioctl() requests. The argument fd must be an open file descriptor
- **getenv** : `char *getenv(const char *name);` searches the environment list to find the environment variable name, and returns a pointer to the corresponding value string, or NULL if not found
- **tcsetattr** : `int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);` tcsetattr() only works in an environment where either a controlling terminal exists, or stdin and stderr refer to tty devices. Specifically, it does not work in a TSO environment. Changes the attributes associated with a terminal. New attributes are specified with a termios control structure. Programs should always issue a tcgetattr() first, modify the desired fields, and then issue a tcsetattr(). tcsetattr() should never be issued using a termios structure that was not obtained using tcgetattr(). tcsetattr() should use only a termios structure that was obtained by tcgetattr()
- **tcgetattr** : `int tcgetattr(int fildes, struct termios *termptr);` Gets a termios structure, which contains control information for a terminal associated with fildes. It stores that information in a memory location that termptr points to. The contents of a termios structure are described in tcsetattr()
## ressources :
- [termcap](https://www.gnu.org/software/termutils/manual/termcap-1.3/html_chapter/termcap_toc.html)
- [readline](https://tiswww.case.edu/php/chet/readline/rltop.html)
- [readline](https://tiswww.case.edu/php/chet/readline/README)
- [transformer arbre normal en arbre binaire](https://fr.wikipedia.org/wiki/Arbre_binaire#Transformation_d'un_arbre_quelconque_en_un_arbre_binaire)
- [send EOF to process](https://unix.stackexchange.com/questions/493578/how-to-send-d-eot-character-to-stdin-of-a-shell-process)
- [get root access 1](https://vitux.com/how-to-become-root-user-in-ubuntu-command-line-using-su-and-sudo/)
- [get root access using sudo su](https://superuser.com/questions/408990/how-do-i-log-out-of-sudo-su)
- [what is a tty](https://www.howtogeek.com/428174/what-is-a-tty-on-linux-and-how-to-use-the-tty-command/)
- [signal in a child process](https://stackoverflow.com/questions/55190460/using-signals-in-a-child-process)
- [send signal to process and childs](https://linuxconfig.org/how-to-propagate-a-signal-to-child-processes-from-a-bash-script)
- [exit code status](https://tldp.org/LDP/abs/html/exitcodes.html)
- [`char **s` vs `char *s[]`](https://stackoverflow.com/questions/46830654/what-is-the-difference-between-extern-char-environ-and-extern-char-environ)
- [extern and global](https://stackoverflow.com/questions/2652545/extern-and-global-in-c)
- [PS1 variable contain prompt](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03)
- [force readline return without pressing ctrl-c](https://stackoverflow.com/questions/53165704/readline-c-force-return-of-certain-text-in-readline)
**bash scripts :**
- [on which stream deos bash redirect its prompt](https://unix.stackexchange.com/questions/20826/which-stream-does-bash-write-its-prompt-to)
- [fd redirections &](https://putaindecode.io/articles/maitriser-les-redirections-shell)
- [fd redirections &-](https://wiki.bash-hackers.org/howto/redirection_tutorial)
- [redirect prompt output](https://stackoverflow.com/questions/2559076/how-do-i-redirect-output-to-a-variable-in-shell)
- [read, pipes, process substitution](https://stackoverflow.com/questions/15184358/how-to-avoid-bash-command-substitution-to-remove-the-newline-character)
- [process substitution](https://www.linuxjournal.com/content/shell-process-redirection)
- [read, IFS](https://unix.stackexchange.com/questions/164508/why-do-newline-characters-get-lost-when-using-command-substitution)
- [process substitution](https://www.gnu.org/software/bash/manual/bash.html#Process-Substitution)
- [variable substitution](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html)
- [send one command to two pipes](https://stackoverflow.com/questions/13107783/pipe-output-to-two-different-commands)
- [send two commands to one pipe](https://askubuntu.com/questions/133386/how-to-merge-and-pipe-results-from-two-different-commands-to-single-command)
- ["\[" vs "\[\[" in bash](https://stackoverflow.com/questions/13542832/difference-between-single-and-double-square-brackets-in-bash)
- [redirections in bash](https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean)
- [bash variable of variable](https://stackoverflow.com/questions/10757380/bash-variable-variables)
- [bash fork &](https://unix.stackexchange.com/questions/7608/does-bash-support-forking-similar-to-cs-fork/7609#7609)
- [read a var line by line](https://unix.stackexchange.com/questions/9784/how-can-i-read-line-by-line-from-a-variable-in-bash)
- [wait for not-a-child process to finish](https://stackoverflow.com/questions/1058047/wait-for-a-process-to-finish)
-12
View File
@@ -1,12 +0,0 @@
builds
echo
headers
libft
Makefile
minishell
minishell.en.subject.pdf
README.md
ressources
srcs
tests
valgrind_readline.supp
+12 -7
View File
@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/03 19:14:46 by lperrey #+# #+# */
/* Updated: 2021/10/13 16:09:32 by lperrey ### ########.fr */
/* Updated: 2021/11/27 09:09:31 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -15,6 +15,7 @@
# include "libft.h"
# include <fcntl.h>
# include <unistd.h>
# include <sys/ioctl.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
@@ -26,15 +27,19 @@
# include <signal.h>
# include <dirent.h>
# include <termios.h>
# include <curses.h> // sudo apt install libncurses-dev (OR libncurses5-dev)
// sudo apt install libncurses-dev (OR libncurses5-dev)
# include <curses.h>
# include <term.h>
# include <stdio.h>
# include <readline/readline.h> // sudo apt install libreadline-dev
// sudo apt install libreadline-dev
# include <readline/readline.h>
# include <readline/history.h>
# include "minishell_structs.h"
# include <stdio.h>
# include "minishell_macro.h"
# include "minishell_structs.h"
# include "minishell_term_colors.h"
# include "minishell_user_macro.h"
# include "minishell_prototypes.h"
@@ -52,8 +57,8 @@
** <fcntl.h>: open()
** <unistd.h>: read(), write(), close(), fork(), getcwd(), chdir(),
** stat(), lstat(), fstat(), execve(), dup(), dup2(), pipe(),
** isatty(), ttyname(), ttyslot(), ioctl(),
** tcsetattr(), tcgetattr()
** isatty(), ttyname(), ttyslot(), tcsetattr(), tcgetattr()
** <sys/ioctl.h>: ioctl()
** <stdlib.h>: malloc(), free(), exit(), getenv()
** <string.h>: strerror(), define NULL, define size_t
** <errno.h>: define errno
+34 -1
View File
@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:35:55 by lperrey #+# #+# */
/* Updated: 2021/10/08 03:01:43 by lperrey ### ########.fr */
/* Updated: 2021/11/27 10:43:43 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -18,4 +18,37 @@
# define PROMPT_CHEVRON "> "
# define PROMPT_EURO "\001€\002 \001\b\002"
# define EXIT_CMD_NOT_FOUND 127
# define EXIT_CMD_NOT_EXE 126
# define EXIT_SIGNAL 128
// 1 and 125 inclusive
# define EXIT_REDIRECTION 22
# define EXIT_EXPANSION 33
enum e_lexer_return
{
CONTINUE_TOKEN = 1,
DELIMITE_TOKEN
};
enum e_token_id
{
T_LESS = '<',
T_GREAT = '>',
T_PIPE = '|',
T_DLESS,
T_DGREAT,
T_WORD,
T_REDIRECTION_WORD
};
// T_DLESS == '<<'
// T_DGREAT == '>>'
enum e_quotes_state
{
IN_QUOTES = '\'',
IN_DQUOTES = '\"'
};
#endif
+76 -4
View File
@@ -6,26 +6,98 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */
/* Updated: 2021/10/10 23:55:14 by lperrey ### ########.fr */
/* Updated: 2021/12/18 12:31:33 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MINISHELL_PROTOTYPES_H
# define MINISHELL_PROTOTYPES_H
int g_switch_heredoc_sigint;
extern char **environ;
// Init
int init(t_all *c, char *envp[]);
int init(t_all *c, char *argv[]);
char *init_prompt(char *prompt_base);
char **retrieve_path(void);
void set_signals_behaviour(void);
// Shell modes
void shell_loop(t_all *c);
void shell_script(t_all *c);
// Lexer
t_token *lexing(char *input);
// Parser
t_cmd **parsing(t_token *token_list);
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);
// Exec
int exec_cmd_line(t_all *c);
int pipeline(t_all *c);
int cmd_find_access(t_cmd *cmd, char *path[]);
int cmd_exec_in_subshell(t_cmd *cmd, t_all *c);
void wait_subshell(pid_t last_cmd_pid);
int simple_command_builtin(t_cmd *cmd, t_all *c);
// Builtins
int builtin_env(int argc, char *argv[], t_all *c);
int builtin_cd(int argc, char *argv[], t_all *c);
int builtin_pwd(int argc, char *argv[], t_all *c);
int builtin_export(int argc, char *argv[], t_all *c);
int export_var(char *arg);
int builtin_unset(int argc, char *argv[], t_all *c);
int builtin_exit(int argc, char *argv[], t_all *c);
int builtin_env(int argc, char *argv[], t_all *c);
int builtin_echo(int argc, char *argv[], t_all *c);
// Free
int free_exit(t_all *c, int exit_status);
int exit_free(t_all *c, int exit_status);
void free_pipeline(t_cmd **pipeline_ptr[]);
void close_pipeline_fd(t_cmd *pipeline[]);
void close_stdio(void);
typedef void (*t_free_f)(void *); // generic
// Error wrappers
int shell_error(char *s1, char *s2, char *s3, int ret_val);
int shell_perror(char *s1, char *s2, char *s3, int ret_val);
int ft_reti_perror_io(int ret, char *err_str, char *io_file);
// Generic
char *ft_strjoinfree(char *s1, char *s2);
char *ft_strjoinfree_s1(char *s1, const char *s2);
char *ft_strjoinfree_s2(const char *s1, char *s2);
void ft_lstprint(t_list *lst, int fd);
int ft_isinset_str(char *str, char *set);
size_t ft_2d_arrlen(void *ptr); // Replace ft_arrlen()
char **ft_dup_2d_char_arr(char **ptr);
void *ft_resize_2d_arr(void *ptr, size_t add_nbr);
t_list *ft_lstbeforelast(t_list *lst);
void *ft_lstnew_generic(size_t lst_size, size_t content_size);
typedef void *(*t_dup_f)(void *);
void *ft_dup_2d_arr(void *ptr, void *(*dup_func)(void *));
void ft_free_null(void *ptr);
char *ft_getenv(char *env_var);
size_t ft_getenv_position(char *env_var);
int ft_is_posix_name(char *str);
char **ft_split_quotes(char const *s, char c);
char *ft_strdup_quotes(const char *s);
// Signals handler
void sigint_handler_interactive(int signum);
void sigint_handler_heredoc(int signum);
// last_exit_status
int set_last_exit_status(int new_value);
int get_last_exit_status(void);
#endif
+26 -2
View File
@@ -6,18 +6,42 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */
/* Updated: 2021/10/10 05:39:09 by lperrey ### ########.fr */
/* Updated: 2021/12/16 06:34:29 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MINISHELL_STRUCTS_H
# define MINISHELL_STRUCTS_H
struct s_all;
typedef struct s_token
{
char *content;
struct s_token *next;
enum e_token_id id;
} t_token;
typedef int (*t_builtin_f)(int,char **,struct s_all *);
typedef struct s_cmd
{
char **argv;
char *path;
t_builtin_f builtin_f;
int fd_in;
int fd_out;
pid_t pid;
int error;
} t_cmd;
typedef struct s_all
{
char **envp;
t_cmd **pipeline;
char **path;
char *prompt_base;
char *prompt;
t_token *token_list;
} t_all;
#endif
+2 -2
View File
@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 03:36:37 by lperrey #+# #+# */
/* Updated: 2021/10/10 20:58:28 by lperrey ### ########.fr */
/* Updated: 2021/10/19 20:30:34 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -15,7 +15,7 @@
# include "minishell_macro.h"
# define U_PROMPT_END PROMPT_EURO
# define U_PROMPT_END PROMPT_CHEVRON
# define U_DEFAULT_USER "NoUser"
# define U_DEFAULT_NAME "NoName"
+1 -1
Submodule libft updated: 1401fddfcd...af88c1ce23
+1
Submodule minishell_tests added at 863e48a4fa
+102
View File
@@ -0,0 +1,102 @@
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10_02
/* -------------------------------------------------------
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_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
| LESSAND filename
| '>' filename
| GREATAND filename
| DGREAT filename
| LESSGREAT filename
| CLOBBER filename
;
filename : WORD // Apply rule 2
;
io_here : DLESS here_end
;
here_end : WORD // Apply rule 3
;
/* -------------------------------------------------------
The Grammar
------------------------------------------------------- */
%start program
%%
pipeline : pipe_sequence
;
pipe_sequence : command
| pipe_sequence '|' command
;
command : simple_command
;
simple_command : cmd_prefix cmd_word cmd_suffix
| cmd_prefix cmd_word
| cmd_prefix
| cmd_name cmd_suffix
| cmd_name
;
cmd_name : WORD /* Apply rule 7a */
;
cmd_word : WORD /* Apply rule 7b */
;
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
| LESSAND filename
| '>' filename
| GREATAND filename
| DGREAT filename
| LESSGREAT filename
| CLOBBER filename
;
filename : WORD /* Apply rule 2 */
;
io_here : DLESS here_end
;
here_end : WORD /* Apply rule 3 */
;
-1
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
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/08 22:33:56 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 = init_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
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);
}
+4 -3
View File
@@ -6,16 +6,17 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 05:01:26 by lperrey #+# #+# */
/* Updated: 2021/10/10 07:37:29 by lperrey ### ########.fr */
/* Updated: 2021/12/01 17:19:48 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int builtin_env(int argc, char *argv[], t_all *c) // WIP
int builtin_env(int argc, char *argv[], t_all *c)
{
(void)argc;
(void)argv;
ft_putendl_arr_fd(c->envp, 1);
(void)c;
ft_putendl_arr_fd(environ, 1);
return (0);
}
+4 -4
View File
@@ -6,18 +6,18 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 05:01:22 by lperrey #+# #+# */
/* Updated: 2021/10/11 01:50:53 by lperrey ### ########.fr */
/* Updated: 2021/11/29 12:43:47 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int builtin_exit(int argc, char *argv[], t_all *c) // WIP
int builtin_exit(int argc, char *argv[], t_all *c)
{
unsigned char status;
int i;
status = 0;
status = get_last_exit_status();
if (argc > 2)
return (ft_reti_print(1, "exit: too many arguments\n", 2));
if (argc == 2)
@@ -38,5 +38,5 @@ int builtin_exit(int argc, char *argv[], t_all *c) // WIP
}
status = ft_atoi(argv[1]);
}
return (free_exit(c, status));
return (exit_free(c, status));
}
+94
View File
@@ -0,0 +1,94 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* export.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/03 13:36:54 by lperrey #+# #+# */
/* Updated: 2021/12/06 03:19:30 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)
c->path = retrieve_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;
ret = 0;
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);
}
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
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
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/19 12:10:57 by hulamy ### ########.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)
c->path = retrieve_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
*/
+35
View File
@@ -0,0 +1,35 @@
#include "minishell.h"
// pour imprimer une char ** en precisant comment separer les char *
void print_matrix(char **matrix, char *sep)
{
int i;
i = 0;
while (matrix[i])
{
printf("%s", matrix[i]);
if (matrix[i + 1])
printf("%s", sep);
//fflush(stdout);
i++;
}
write(1, "\n", 1);
}
void print_pipeline(t_cmd **pipeline)
{
int i;
i = 0;
while (pipeline[i])
{
printf("CMD %i, fd_in=%i, fd_out=%i\n", i, pipeline[i]->fd_in, pipeline[i]->fd_out);
ft_putstr_fd(" |", 1);
print_matrix(pipeline[i]->argv, "|\n |");
i++;
if (pipeline[i])
ft_putstr_fd("----------------\n", 1);
}
}
+29
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/05 14:09:43 by hulamy ### ########.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
*/
+113
View File
@@ -0,0 +1,113 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* find_access.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/16 05:57:42 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
*/
// TODO : faire des test sur la valeur de errno selon les cas (if directory, if pathname invalid, ...)
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);
}
+107
View File
@@ -0,0 +1,107 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pipeline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/16 15:55:36 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 (pipeline[0]->builtin_f && ft_2d_arrlen(pipeline) == 1)
{
if (!pipeline[0]->error)
{
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);
}
i++;
}
close_pipeline_fd(c->pipeline);
i -= 1;
if (pipeline[i]->error)
set_last_exit_status(pipeline[i]->error);
return (pipeline[i]->pid);
}
+63
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);
}
+41
View File
@@ -0,0 +1,41 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* subshell_exec.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"
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)
exit_free(c, cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c));
else if (execve(cmd->path, cmd->argv, environ) == -1)
return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0]));
}
return (EXIT_SUCCESS);
}
+53
View File
@@ -0,0 +1,53 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* subshell_wait.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/11/27 10:43:46 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
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))
{
write(STDIN_FILENO, "\n", 1);
set_last_exit_status(EXIT_SIGNAL + WTERMSIG(wstatus));
}
}
ret = 0;
while (ret != -1)
{
ret = wait(&wstatus);
if (ret == -1)
ret = handle_wait_error();
}
}
static int handle_wait_error(void)
{
if (errno == ECHILD)
return (-1);
else if (errno == EINTR)
return (0);
else
perror("wait()");
return (-1);
}
+67
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);
}
+6 -7
View File
@@ -1,20 +1,19 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* free.c :+: :+: :+: */
/* ft_free_null.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
/* Updated: 2021/10/10 23:59:25 by lperrey ### ########.fr */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/16 03:59:21 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int free_exit(t_all *c, int exit_status)
void ft_free_null(void *ptr)
{
free(c->prompt_base);
free(c->prompt);
exit(exit_status);
free(*(char **)ptr);
*(char **)ptr = NULL;
}
+70
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/16 03:44:06 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 (environ[i][env_var_len] == '=')
{
if (ft_strncmp(environ[i], env_var, env_var_len) == 0)
found = 1;
else
i++;
}
else
i++;
}
return (i);
}
+31
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);
}
+37
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);
}
+56
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);
}
+106
View File
@@ -0,0 +1,106 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_split_MODIF.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/13 07:08:40 by lperrey #+# #+# */
/* Updated: 2021/11/13 20:24:33 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
// FT_SPLIT LEGEREMENT REMANIER.
// A REMPLACER DANS LA LIBFT
#include "libft.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);
char **ft_split(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;
count = 0;
i = 0;
while (s[i])
{
while (s[i] == c)
i++;
if (s[i])
count++;
while (s[i] && s[i] != c)
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;
i = 0;
arr_i = 0;
while (arr_i < words_count)
{
len = 0;
while (s[i] == c)
i++;
while (s[i] && s[i] != c)
{
len++;
i++;
}
str_arr[arr_i] = malloc(len + 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;
i = 0;
arr_i = 0;
while (str_arr[arr_i])
{
while (s[i] == c)
i++;
char_i = 0;
while (s[i] && s[i] != c)
str_arr[arr_i][char_i++] = s[i++];
str_arr[arr_i][char_i] = '\0';
arr_i++;
}
}
+179
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/11/26 21:27:10 by lperrey ### ########.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'; //superflu si ft_calloc
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], '\'')) // if closed quotes
*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], '\"')) // if closed quotes
*quote_state = IN_DQUOTES;
else
return (0);
return (1);
}
return (0);
}
+64
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/11/26 21:27:05 by lperrey ### ########.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], '\'')) // if closed quotes
*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], '\"')) // if closed quotes
*quote_state = IN_DQUOTES;
else
return (0);
return (1);
}
return (0);
}
@@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* generic.c :+: :+: :+: */
/* ft_strjoinfree.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/10/08 09:28:49 by lperrey ### ########.fr */
/* Updated: 2021/12/16 03:39:09 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
+62
View File
@@ -0,0 +1,62 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* handle_argv.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/18 04:46:05 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int remap_stdin_to_script_file(char *script_file);
char *init_prompt_base(void);
int handle_argv(t_all *c, char *argv[])
{
int ret;
if (argv[1])
{
ret = remap_stdin_to_script_file(argv[1]);
if (ret)
exit_free(c, ret);
}
else if (isatty(STDIN_FILENO))
{
c->prompt_base = init_prompt_base();
if (!c->prompt_base)
return (ft_reti_perror(0, "init_prompt_base()"));
c->prompt = init_prompt(c->prompt_base);
if (!c->prompt)
return (ft_reti_perror(0, "init_prompt()"));
}
return (1);
}
int remap_stdin_to_script_file(char *script_file)
{
int fd;
int ret;
int tmp;
fd = open(script_file, O_RDONLY);
if (fd == -1)
{
shell_perror(script_file, ": ", "", 0);
return (EXIT_CMD_NOT_FOUND);
}
ret = dup2(fd, STDIN_FILENO);
tmp = errno;
if (close(fd) == -1)
perror("close()");
if (ret == -1)
{
errno = tmp;
return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
}
return (0);
}
+33
View File
@@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* init.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/18 14:22:20 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void init_readline(void);
int init_shlvl(void);
int handle_argv(t_all *c, char *argv[]);
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)"));
c->path = retrieve_path();
if (!init_shlvl())
return (ft_reti_perror(0, "init_shlvl()"));
if (!handle_argv(c, argv))
return (0);
return (1);
}
+16 -20
View File
@@ -1,34 +1,18 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* init.c :+: :+: :+: */
/* init_prompt.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/10/10 21:56:33 by lperrey ### ########.fr */
/* Updated: 2021/12/18 12:33:50 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static char *init_prompt_base(void);
static char *init_prompt(char *prompt_base);
int init(t_all *c, char *envp[])
{
ft_bzero(c, sizeof *c);
c->envp = envp;
c->prompt_base = init_prompt_base();
if (!c->prompt_base)
return (ft_reti_perror(0, "init_prompt_base() fail"));
c->prompt = init_prompt(c->prompt_base);
if (!c->prompt)
return (ft_reti_perror(0, "init_prompt() fail"));
return (1);
}
static char *init_prompt_base(void)
char *init_prompt_base(void)
{
char *prompt_base;
char *tmp;
@@ -39,20 +23,32 @@ static char *init_prompt_base(void)
if (!tmp)
tmp = U_DEFAULT_USER;
prompt_base = ft_strjoin(TERM_LIGHT_GREEN, tmp);
if (!prompt_base)
return (NULL);
prompt_base = ft_strjoinfree_s1(prompt_base, "@");
if (!prompt_base)
return (NULL);
tmp = getenv("NAME");
if (!tmp)
tmp = U_DEFAULT_NAME;
prompt_base = ft_strjoinfree_s1(prompt_base, tmp);
if (!prompt_base)
return (NULL);
prompt_base = ft_strjoinfree_s1(prompt_base, TERM_RESET":"TERM_LIGHT_BLUE);
if (!prompt_base)
return (NULL);
return (prompt_base);
}
static char *init_prompt(char *prompt_base)
char *init_prompt(char *prompt_base)
{
char *prompt;
prompt = ft_strjoinfree_s2(prompt_base, getcwd(NULL, 0));
if (!prompt)
return (NULL);
prompt = ft_strjoinfree_s1(prompt, TERM_RESET U_PROMPT_END);
if (!prompt)
return (NULL);
return (prompt);
}
+33
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
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);
}
+65
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
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
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
*/
+7 -62
View File
@@ -6,77 +6,22 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
/* Updated: 2021/10/10 15:13:26 by hulamy ### ########.fr */
/* Updated: 2021/12/18 05:08:48 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void shell_loop(t_all *c)
{
char *line_input;
line_input = NULL;
while (1)
{
if (line_input)
free(line_input);
line_input = readline(c->prompt);
if (line_input && *line_input)
{
if (!ft_strncmp(line_input, "env", 4)) // temp placeholder
builtin_env(0, NULL, c);
else if (!ft_strncmp(line_input, "exit", 5)) // temp placeholder
builtin_exit(0, NULL, c);
else
printf("echo: %s\n", line_input);
}
}
}
void wip_test()
{
char term_desc[2048];
char *term_type;
int term_width;
int term_height;
int ret;
term_type = getenv("TERM");
if (term_type == 0)
ft_putstr_fd("Specify a terminal type with `setenv TERM <yourtype>'.\n", 2);
ret = tgetent(term_desc, term_type);
if (ret < 0)
ft_putstr_fd("Could not access the termcap data base.\n", 2);
if (ret == 0)
ft_putstr_fd("Terminal type `%s' is not defined.\n", 2);
term_height = tgetnum ("li");
term_width = tgetnum ("co");
/* Extract information that termcap functions use. */
/* temp = tgetstr ("pc", BUFFADDR);
PC = temp ? *temp : 0;
BC = tgetstr ("le", BUFFADDR);
UP = tgetstr ("up", BUFFADDR); */
}
int main(int argc, char *argv[], char *envp[])
int main(int argc, char *argv[])
{
t_all c;
(void)argc;
(void)argv;
if (!init(&c, envp))
exit(EXIT_FAILURE);
if (!init(&c, argv))
exit_free(&c, EXIT_FAILURE);
if (!isatty(STDIN_FILENO))
shell_script(&c);
else
shell_loop(&c);
return (0);
}
/*
** idea about malloc protection :
** have them(mallocand 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);
*/
+52
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);
}
+84
View File
@@ -0,0 +1,84 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* free.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
/* Updated: 2021/12/18 14:15:13 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 (!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])
{
if (pipeline[i]->fd_in != STDIN_FILENO && pipeline[i]->fd_in > 0)
{
if (close(pipeline[i]->fd_in) == -1)
perror("close()");
pipeline[i]->fd_in = 0;
}
if (pipeline[i]->fd_out != STDOUT_FILENO && pipeline[i]->fd_out > 0)
{
if (close(pipeline[i]->fd_out) == -1)
perror("close()");
pipeline[i]->fd_out = 0;
}
i++;
}
}
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()");
}
+37
View File
@@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* last_exit_status.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/26 19:02:27 by lperrey #+# #+# */
/* Updated: 2021/11/26 20:48:11 by lperrey ### ########.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));
}
/* void ALT_set_last_exit_status(int new_value, int *set_last_exit_status_ptr)
{
static int *last_exit_status_ptr = NULL;
if (set_last_exit_status_ptr)
last_exit_status_ptr = set_last_exit_status_ptr;
else if (new_value >= 0)
*last_exit_status_ptr = new_value;
} */
+27
View File
@@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* retrieve_path.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/08 06:27:23 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
char **retrieve_path(void)
{
char *path;
char **path_split;
path = getenv("PATH");
if (!path)
return (ft_retp_print(NULL, "minishell: Warning, $PATH not set\n", 2));
path_split = ft_split(path, ':');
if (!path_split)
return (ft_retp_perror(NULL, "retrieve_path()"));
return (path_split);
}
+39
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/19 12:11:14 by hulamy ### ########.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);
}
+95
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);
}
+135
View File
@@ -0,0 +1,135 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* expand_token.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/16 14:51:33 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static t_list *content_copy(char *content, int *i, int *quotes_state);
static t_list *content_expand(char *content, int *i);
static char *env_var_expansion(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)
{//todo wrap
perror("expand_token() error");
return (ft_lstclear(&head.next, free));
}
}
return (head.next);
}
static 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] && (content[*i] != '$' || *quotes_state == IN_QUOTES))
{
if (content[*i] == '\'' && *quotes_state != IN_DQUOTES)
{
if (*quotes_state == IN_QUOTES)
*quotes_state = 0;
else
*quotes_state = IN_QUOTES;
}
((char *)expand->content)[i_exp++] = content[(*i)++];
}
return (expand);
}
static 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 *retrieve_var(char *content, int *i);
static char *env_var_expansion(char *content, int *i)
{
char *expansion;
(*i)++; // skip '$'
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); // *i - 1 for '$' skip
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
*/
+82
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/16 14:50:58 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;
// 1
tmp = (t_list*)expand_token(t->content);
if (!tmp)
return (0);
// 2
tmp = (char*)rejoin_after_expand(tmp);
if (!tmp)
return (0);
// 3
tmp_split = ft_split_quotes(tmp, ' ');
free(tmp);
if (!tmp_split)
return (0);
// 4
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);
// 5
if (!new_token_for_each_field(tmp_split, t))
return (0);
return (1);
}
@@ -0,0 +1,61 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* new_token_for_each_field.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/16 14:50:36 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)
{//todo wrap
perror("insert_token_for_each_field() error");
ft_free_2d_arr(fields);
return ((int)ft_lstclear((t_list **)&head.next, NULL));
}
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;
//return (insert_lst_last); // return inutile pour reusinage
}
@@ -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/11/07 04:03:02 by lperrey ### ########.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)
{//todo wrap
perror("rejoin_after_expand() error");
return (ft_lstclear(&head, free));
}
expand_lst = expand_lst->next;
}
ft_lstclear(&head, free);
return (result);
}
+121
View File
@@ -0,0 +1,121 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* parsing.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */
/* Updated: 2021/12/17 17:45:25 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void save_redirections_words(t_token *t);
t_cmd **parsing(t_token *token_list)
{
t_cmd **pipeline;
if (!valid_syntax(token_list))
return (NULL);
// 2.9.1 - 1) Save Words
save_redirections_words(token_list);
// Struct CMD alloc
pipeline = pipeline_alloc(1 + count_pipes(token_list));
if (!pipeline)
return (NULL);
// 2.9.1 - 2) Expansion
if (!expansions(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
// 2.9.1 - 3) Redirection
if (!redirections(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
// Struct CMD fill
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
;
*/
+161
View File
@@ -0,0 +1,161 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* here_doc.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/12/19 12:12:27 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static int here_doc_write(char *delimiter, int doc_fd);
static int here_doc_write_interactive(char *delimiter, int doc_fd);
static int here_doc_write_script(char *delimiter, int doc_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 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);
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 ret;
struct sigaction signal_action;
if (isatty(STDIN_FILENO))
{
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);
}
else
{
ret = here_doc_write_script(delimiter, doc_fd);
}
return (ret);
}
static int here_doc_write_interactive(char *delimiter, int doc_fd)
{
char *line;
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));
if (ft_strncmp(line, delimiter, ft_strlen(line) + 1) == 0) // Ou ft_strlen(delimiter) + 1 ? Ça devrais être identique et ça peux se calculer une seul fois.
break ;
if (write(doc_fd, line, ft_strlen(line)) == -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)
{
char *line;
int ret;
line = NULL;
ret = 1;
while (ret)
{
ret = gnl(STDIN_FILENO, &line, 0);
if (ret == -1)
return (ft_reti_perror_free(-1, line, free, "gnl() STDIN"));
if (ft_strncmp(line, delimiter, ft_strlen(line) + 1) == 0) // Ou ft_strlen(delimiter) + 1 ? Ça devrais être identique et ça peux se calculer une seul fois.
break ;
if (write(doc_fd, line, ft_strlen(line)) == -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.
*/
+137
View File
@@ -0,0 +1,137 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* redirections.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/12/16 14:49:28 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int here_doc(char *delimiter);
static int redirect_cmd_input(t_token *t, t_cmd *cmd);
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 i;
i = 0;
while (t)
{
if (t->id == '|')
i++;
if (!pipeline[i]->error)
{
if (t->id == '<' || t->id == T_DLESS)
{
if (!redirect_cmd_input(t, pipeline[i]))
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 (t->id == '<')
{
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;
}
}
else if (t->id == T_DLESS)
{
cmd->fd_in = here_doc(t->next->content);
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; // Eventuellement a integrer dans token_expansions()
if (ft_lstsize((t_list *)head->next) != 1)
{
ret = 0;
shell_error("", "", "ambiguous redirect", 0);
}
((t_token *)ft_lstlast((t_list *)head))->next = next_token;
return (ret);
}
+83
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/17 03:18:49 by lperrey ### ########.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)
{
while (valid_io_redirect(token_list))
{
if (valid_token(token_list, T_WORD))
{
while (valid_token(token_list, T_WORD)
|| valid_io_redirect(token_list))
{
if (valid_command_separator(*token_list))
return (1);
}
}
}
return (0);
}
// cmd_prefix cmd_name
int valid_command_rule2(t_token **token_list)
{
while (valid_io_redirect(token_list))
{
if (valid_token(token_list, T_WORD))
{
if (valid_command_separator(*token_list))
return (1);
}
}
return (0);
}
// cmd_name cmd_suffix
int valid_command_rule3(t_token **token_list)
{
if (valid_token(token_list, T_WORD))
{
while (valid_token(token_list, T_WORD) || valid_io_redirect(token_list))
{
if (valid_command_separator(*token_list))
return (1);
}
}
return (0);
}
// cmd_name
int valid_command_rule4(t_token **token_list)
{
if (valid_token(token_list, T_WORD))
{
if (valid_command_separator(*token_list))
return (1);
}
return (0);
}
// cmd_prefix
int valid_command_rule5(t_token **token_list)
{
while (valid_io_redirect(token_list))
{
if (valid_command_separator(*token_list))
return (1);
}
return (0);
}
+41
View File
@@ -0,0 +1,41 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* valid_command.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */
/* Updated: 2021/12/17 03:28:53 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);
return (0);
}
@@ -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);
}
@@ -0,0 +1,28 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* valid_pipeline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:51:35 by lperrey #+# #+# */
/* Updated: 2021/10/24 19:35:16 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
int valid_command(t_token **token_list);
int valid_pipeline(t_token **token_list)
{
while (valid_command(token_list))
{
if (*token_list == NULL)
return (1);
else if ((*token_list)->id != '|' || (*token_list)->next == NULL)
return (0);
valid_token(token_list, '|');
}
return (0);
}
+45
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);
}
+60
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/18 12:34:08 by hulamy ### ########.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);
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
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/18 15:15:30 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
static char *read_input_script(t_all *c);
static void exit_signal(t_all *c);
void shell_script(t_all *c)
{
char *line_input;
line_input = NULL;
while (1)
{
free(line_input);
line_input = read_input_script(c);
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);
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)
{
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(STDIN_FILENO, &line_input, 0);
if (ret == -1)
{
free(line_input);
return (NULL);
}
if (!line_input[0] && ret == 0)
{
free(line_input);
exit_free(c, get_last_exit_status());
}
return (line_input);
}
static void exit_signal(t_all *c)
{
write(STDOUT_FILENO, "\n", 1);
exit_free(c, get_last_exit_status());
}
+17
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);
}
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# trap ctrl-c and call ctrl_c()
trap ctrl_c INT
function ctrl_c() {
echo "** Trapped CTRL-C"
}
for i in `seq 1 5`; do
sleep 1
echo -n "."
done
+7
View File
@@ -4,3 +4,10 @@
...
fun:readline
}
{
<readline history>
Memcheck:Leak
...
fun:add_history
}