26 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
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
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
hugogogo
424e2563ac commit change in readme 2021-12-16 14:45:42 +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
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
hugogogo
a485b3046e ajouts des tests discord 2021-12-05 18:26:44 +01:00
hugogogo
39908b71d9 debug du heredoc en pipeline finalement la cause est rldone 2021-12-05 17:44:26 +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
hugogogo
a288ad473e test unitaires a peu pres ok :) 2021-12-03 22:32:07 +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
hugogogo
6a077174bc debut ecriture test_unitaires var assign resultat de plusieurs commandes 2021-11-30 22:34:34 +01:00
43 changed files with 818 additions and 486 deletions

View File

@@ -2,7 +2,7 @@ NAME = minishell
CC = clang CC = clang
CFLAGS = -Wall -Wextra -Werror $(INCLUDES) # add -g CFLAGS = -Wall -Wextra $(INCLUDES) -g # add -Werror, del -g
VPATH = $(DIR_SRCS) VPATH = $(DIR_SRCS)
DIR_SRCS = srcs \ DIR_SRCS = srcs \
@@ -31,16 +31,14 @@ LIBFT = $(LIBFT_D)/libft.a
SRCS = main.c \ SRCS = main.c \
shell_loop.c shell_script.c \ shell_loop.c shell_script.c \
init.c init_prompt.c init_readline.c init_shlvl.c open_script_file.c \ init.c init_prompt.c init_readline.c init_shlvl.c handle_argv.c \
retrieve_path.c \ retrieve_path.c \
free.c \ free.c \
signals.c error_wrappers.c last_exit_status.c \ signals.c error_wrappers.c last_exit_status.c \
lexing.c fill_token.c check_operators.c \ lexing.c fill_token.c check_operators.c \
parsing.c create_pipeline.c \ parsing.c create_pipeline.c \
valid_syntax.c valid_pipeline.c valid_command.c rules_command.c valid_io_redirect.c \ valid_syntax.c valid_pipeline.c valid_command.c rules_command.c valid_io_redirect.c \
expansions.c \ expansions.c expand_token.c rejoin_after_expand.c new_token_for_each_field.c \
expand_token.c content_expand.c content_copy.c \
rejoin_after_expand.c new_token_for_each_field.c \
redirections.c here_doc.c \ redirections.c here_doc.c \
exec_cmd_line.c pipeline.c \ exec_cmd_line.c pipeline.c \
find_access.c subshell_exec.c subshell_wait.c simple_cmd_builtin.c \ find_access.c subshell_exec.c subshell_wait.c simple_cmd_builtin.c \

164
README.md Normal file
View File

@@ -0,0 +1,164 @@
## todo list :
---
- **global features :**
- `prompt` *show a prompt*
- `history` *use history with arrows*
- `binaries` *fetch and launch the right executable*
- `'` `"` `;` `\` *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* [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 :** [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 --*
- `>>` *redirect and append*
- **signals :**
- `^C` *close process*
- `^D` *exit minishell*
- `^\` *do nothing*
- **builtins :** (can't be executed in child process)
- `cd <relative path>`
- `cd <absolute path>`
- `pwd`
- `export`
- `unset`
- `exit`
- **builtins :** (but they don't need to be)
- `env`
- `echo`
- `echo -n`
## allowed external functions :
---
(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)

View File

@@ -6,31 +6,31 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */ /* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:28:07 by lperrey ### ########.fr */ /* Updated: 2021/12/18 12:31:33 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef MINISHELL_PROTOTYPES_H #ifndef MINISHELL_PROTOTYPES_H
# define MINISHELL_PROTOTYPES_H # define MINISHELL_PROTOTYPES_H
extern int g_switch_heredoc_sigint; int g_switch_heredoc_sigint;
extern char **environ; extern char **environ;
// Init // Init
int init(t_all *c, char *argv[]); int init(t_all *c, char *argv[]);
char *update_prompt(char *prompt_base); char *init_prompt(char *prompt_base);
int retrieve_path(char **path_stock[]); char **retrieve_path(void);
void set_signals_behaviour(void); void set_signals_behaviour(void);
// Shell modes // Shell modes
void shell_loop(t_all *c); void shell_loop(t_all *c);
void shell_script(t_all *c, int script_fd); void shell_script(t_all *c);
// Lexer // Lexer
t_token *lexing(char *input); t_token *lexing(char *input);
// Parser // Parser
t_cmd **parsing(t_token *token_list, int script_fd); t_cmd **parsing(t_token *token_list);
int valid_syntax(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_token(t_token **token_list, enum e_token_id token_id);
int valid_command_separator(const t_token *token_list); int valid_command_separator(const t_token *token_list);
@@ -39,7 +39,7 @@ t_cmd **pipeline_alloc(size_t cmd_nbr);
int pipeline_fill_argv(t_token *token_list, t_cmd **pipeline); int pipeline_fill_argv(t_token *token_list, t_cmd **pipeline);
int expansions(t_token *token_list, t_cmd **pipeline); int expansions(t_token *token_list, t_cmd **pipeline);
int token_expansions(t_token *t); int token_expansions(t_token *t);
int redirections(t_token *token_list, t_cmd **pipeline, int script_fd); int redirections(t_token *token_list, t_cmd **pipeline);
// Exec // Exec
int exec_cmd_line(t_all *c); int exec_cmd_line(t_all *c);
@@ -63,7 +63,6 @@ int builtin_echo(int argc, char *argv[], t_all *c);
int exit_free(t_all *c, int exit_status); int exit_free(t_all *c, int exit_status);
void free_pipeline(t_cmd **pipeline_ptr[]); void free_pipeline(t_cmd **pipeline_ptr[]);
void close_pipeline_fd(t_cmd *pipeline[]); void close_pipeline_fd(t_cmd *pipeline[]);
void close_cmd_fd(t_cmd *cmd);
void close_stdio(void); void close_stdio(void);
typedef void (*t_free_f)(void *); // generic typedef void (*t_free_f)(void *); // generic
@@ -98,7 +97,7 @@ void sigint_handler_interactive(int signum);
void sigint_handler_heredoc(int signum); void sigint_handler_heredoc(int signum);
// last_exit_status // last_exit_status
int set_last_exit_status(int new_value); int set_last_exit_status(int new_value);
int get_last_exit_status(void); int get_last_exit_status(void);
#endif #endif

View File

@@ -6,14 +6,14 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */ /* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:13:45 by lperrey ### ########.fr */ /* Updated: 2021/12/16 06:34:29 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef MINISHELL_STRUCTS_H #ifndef MINISHELL_STRUCTS_H
# define MINISHELL_STRUCTS_H # define MINISHELL_STRUCTS_H
struct s_all; struct s_all;
typedef struct s_token typedef struct s_token
{ {
@@ -42,7 +42,6 @@ typedef struct s_all
char *prompt_base; char *prompt_base;
char *prompt; char *prompt;
t_token *token_list; t_token *token_list;
int script_fd;
} t_all; } t_all;
#endif #endif

1
minishell_tests Submodule

Submodule minishell_tests added at 863e48a4fa

102
parsing.txt Normal file
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 */
;

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/04 19:31:19 by lperrey #+# #+# */ /* Created: 2021/12/04 19:31:19 by lperrey #+# #+# */
/* Updated: 2021/12/20 21:51:00 by lperrey ### ########.fr */ /* Updated: 2021/12/08 22:33:56 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -44,7 +44,7 @@ static int change_prompt(t_all *c)
{ {
char *tmp; char *tmp;
tmp = update_prompt(c->prompt_base); tmp = init_prompt(c->prompt_base);
if (!tmp) if (!tmp)
return (-1); return (-1);
free(c->prompt); free(c->prompt);

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/03 13:36:54 by lperrey #+# #+# */ /* Created: 2021/12/03 13:36:54 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:23:41 by lperrey ### ########.fr */ /* Updated: 2021/12/06 03:19:30 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -35,7 +35,7 @@ int builtin_export(int argc, char *argv[], t_all *c)
else if (ret == ERR_ID) else if (ret == ERR_ID)
exit_value = EXIT_FAILURE; exit_value = EXIT_FAILURE;
if (ft_strncmp(argv[i], "PATH=", 5) == 0) if (ft_strncmp(argv[i], "PATH=", 5) == 0)
retrieve_path(&c->path); c->path = retrieve_path();
i++; i++;
} }
return (exit_value); return (exit_value);
@@ -50,8 +50,7 @@ int export_var(char *arg)
char **var_split; char **var_split;
int ret; int ret;
if (arg[0] != '_' && !ft_isalpha(arg[0])) ret = 0;
return (shell_error("export: ", arg, ERR_ID_STR, ERR_ID));
var_split = ft_split(arg, '='); var_split = ft_split(arg, '=');
if (!var_split) if (!var_split)
return (-1); return (-1);
@@ -61,7 +60,6 @@ int export_var(char *arg)
ft_free_2d_arr(var_split); ft_free_2d_arr(var_split);
return (ERR_ID); return (ERR_ID);
} }
ret = 0;
if (ft_strchr(arg, '=')) if (ft_strchr(arg, '='))
ret = change_var_value(arg, var_split[0]); ret = change_var_value(arg, var_split[0]);
ft_free_2d_arr(var_split); ft_free_2d_arr(var_split);

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/12/05 17:05:05 by lperrey #+# #+# */ /* Created: 2021/12/05 17:05:05 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:23:50 by lperrey ### ########.fr */ /* Updated: 2021/12/19 12:10:57 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -28,7 +28,7 @@ int builtin_unset(int argc, char *argv[], t_all *c)
if (unset_env_var(argv[i]) == EXIT_FAILURE) if (unset_env_var(argv[i]) == EXIT_FAILURE)
exit_value = EXIT_FAILURE; exit_value = EXIT_FAILURE;
if (ft_strncmp(argv[i], "PATH", 4 + 1) == 0) if (ft_strncmp(argv[i], "PATH", 4 + 1) == 0)
retrieve_path(&c->path); c->path = retrieve_path();
i++; i++;
} }
return (exit_value); return (exit_value);

35
srcs/debug.c Normal file
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);
}
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ /* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/01 16:07:48 by lperrey ### ########.fr */ /* Updated: 2021/12/05 14:09:43 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ /* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/22 15:03:31 by lperrey ### ########.fr */ /* Updated: 2021/12/16 05:57:42 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -18,10 +18,12 @@ static t_builtin_f search_builtin(char *cmd_name);
static int handle_access_error(char *file_name); static int handle_access_error(char *file_name);
/* /*
* 2.8.2 Exit Status for Commands 2.8.2 Exit Status for Commands
* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
* #tag_18_08_02 #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[]) int cmd_find_access(t_cmd *cmd, char *path[])
{ {

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ /* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/20 18:08:16 by lperrey ### ########.fr */ /* Updated: 2021/12/16 15:55:36 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -26,21 +26,17 @@ int pipeline(t_all *c)
return (0); return (0);
if (!pipeline_find_access(pipeline, c->path)) if (!pipeline_find_access(pipeline, c->path))
return (0); return (0);
if (ft_2d_arrlen(pipeline) > 1) if (pipeline[0]->builtin_f && ft_2d_arrlen(pipeline) == 1)
wait_subshell(pipeline_exec(pipeline, c));
else
{ {
if (pipeline[0]->error) if (!pipeline[0]->error)
set_last_exit_status(pipeline[0]->error);
else if (pipeline[0]->builtin_f)
{ {
ret = simple_command_builtin(pipeline[0], c); ret = simple_command_builtin(pipeline[0], c);
if (ret != EXIT_SUCCESS) if (ret != EXIT_SUCCESS)
set_last_exit_status(ret); set_last_exit_status(ret);
} }
else
wait_subshell(pipeline_exec(pipeline, c));
} }
else
wait_subshell(pipeline_exec(pipeline, c));
free_pipeline(&c->pipeline); free_pipeline(&c->pipeline);
return (1); return (1);
} }
@@ -101,9 +97,9 @@ static pid_t pipeline_exec(t_cmd *pipeline[], t_all *c)
if (ret != EXIT_SUCCESS) if (ret != EXIT_SUCCESS)
exit_free(c, ret); exit_free(c, ret);
} }
close_cmd_fd(pipeline[i]);
i++; i++;
} }
close_pipeline_fd(c->pipeline);
i -= 1; i -= 1;
if (pipeline[i]->error) if (pipeline[i]->error)
set_last_exit_status(pipeline[i]->error); set_last_exit_status(pipeline[i]->error);

View File

@@ -6,14 +6,12 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ /* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/22 22:12:16 by hulamy ### ########.fr */ /* Updated: 2021/12/01 16:49:37 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
static void exec_builtin(t_cmd *cmd, t_all *c);
int cmd_exec_in_subshell(t_cmd *cmd, t_all *c) int cmd_exec_in_subshell(t_cmd *cmd, t_all *c)
{ {
struct sigaction signal_behaviour; struct sigaction signal_behaviour;
@@ -35,21 +33,9 @@ int cmd_exec_in_subshell(t_cmd *cmd, t_all *c)
return (ft_reti_perror(EXIT_FAILURE, "dup2()")); return (ft_reti_perror(EXIT_FAILURE, "dup2()"));
close_pipeline_fd(c->pipeline); close_pipeline_fd(c->pipeline);
if (cmd->builtin_f) if (cmd->builtin_f)
exec_builtin(cmd, c); exit_free(c, cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c));
else if (execve(cmd->path, cmd->argv, environ) == -1) else if (execve(cmd->path, cmd->argv, environ) == -1)
return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0])); return (ft_reti_perror_io(EXIT_FAILURE, "execve() ", cmd->argv[0]));
} }
return (EXIT_SUCCESS); return (EXIT_SUCCESS);
} }
static void exec_builtin(t_cmd *cmd, t_all *c)
{
struct sigaction signal_behaviour;
int ret;
ft_bzero(&signal_behaviour, sizeof signal_behaviour);
signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &signal_behaviour, NULL);
ret = cmd->builtin_f(ft_2d_arrlen(cmd->argv), cmd->argv, c);
exit_free(c, ret);
}

View File

@@ -6,13 +6,12 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */ /* Created: 2021/11/16 01:57:38 by lperrey #+# #+# */
/* Updated: 2021/12/22 15:38:01 by lperrey ### ########.fr */ /* Updated: 2021/11/27 10:43:46 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
static void handle_signal_status(int wstatus);
static int handle_wait_error(void); static int handle_wait_error(void);
void wait_subshell(pid_t last_cmd_pid) void wait_subshell(pid_t last_cmd_pid)
@@ -28,7 +27,10 @@ void wait_subshell(pid_t last_cmd_pid)
if (WIFEXITED(wstatus)) if (WIFEXITED(wstatus))
set_last_exit_status(WEXITSTATUS(wstatus)); set_last_exit_status(WEXITSTATUS(wstatus));
if (WIFSIGNALED(wstatus)) if (WIFSIGNALED(wstatus))
handle_signal_status(wstatus); {
write(STDIN_FILENO, "\n", 1);
set_last_exit_status(EXIT_SIGNAL + WTERMSIG(wstatus));
}
} }
ret = 0; ret = 0;
while (ret != -1) while (ret != -1)
@@ -37,20 +39,6 @@ void wait_subshell(pid_t last_cmd_pid)
if (ret == -1) if (ret == -1)
ret = handle_wait_error(); ret = handle_wait_error();
} }
if (get_last_exit_status() == EXIT_SIGNAL + SIGSEGV)
ft_putstr_fd("Segmentation fault (core dumped)\n", STDERR_FILENO);
}
static void handle_signal_status(int wstatus)
{
int signum;
signum = WTERMSIG(wstatus);
set_last_exit_status(EXIT_SIGNAL + signum);
if (signum == SIGINT)
write(STDOUT_FILENO, "\n", 1);
if (signum == SIGQUIT)
ft_putstr_fd("Quit (core dumped)\n", STDERR_FILENO);
} }
static int handle_wait_error(void) static int handle_wait_error(void)

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */ /* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */
/* Updated: 2021/12/22 18:07:16 by lperrey ### ########.fr */ /* Updated: 2021/12/16 03:44:06 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -56,9 +56,9 @@ size_t ft_getenv_position(char *env_var)
found = 0; found = 0;
while (!found && environ[i]) while (!found && environ[i])
{ {
if (ft_strncmp(environ[i], env_var, env_var_len) == 0) if (environ[i][env_var_len] == '=')
{ {
if (environ[i][env_var_len] == '=') if (ft_strncmp(environ[i], env_var, env_var_len) == 0)
found = 1; found = 1;
else else
i++; i++;

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++;
}
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/13 07:08:40 by lperrey #+# #+# */ /* Created: 2021/11/13 07:08:40 by lperrey #+# #+# */
/* Updated: 2021/12/20 16:45:10 by hulamy ### ########.fr */ /* Updated: 2021/11/26 21:27:10 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -148,7 +148,7 @@ static void fill_arr(char const *s, char c, char **str_arr)
if (s[i] && (s[i] != c || quote_state)) if (s[i] && (s[i] != c || quote_state))
str_arr[arr_i][char_i++] = s[i++]; str_arr[arr_i][char_i++] = s[i++];
} }
str_arr[arr_i][char_i] = '\0'; str_arr[arr_i][char_i] = '\0'; //superflu si ft_calloc
arr_i++; arr_i++;
} }
} }
@@ -159,7 +159,7 @@ static int quote_state_change(int *quote_state, const char *s)
{ {
if (*quote_state == IN_QUOTES) if (*quote_state == IN_QUOTES)
*quote_state = 0; *quote_state = 0;
else if (ft_strchr(&s[1], '\'')) else if (ft_strchr(&s[1], '\'')) // if closed quotes
*quote_state = IN_QUOTES; *quote_state = IN_QUOTES;
else else
return (0); return (0);
@@ -169,7 +169,7 @@ static int quote_state_change(int *quote_state, const char *s)
{ {
if (*quote_state == IN_DQUOTES) if (*quote_state == IN_DQUOTES)
*quote_state = 0; *quote_state = 0;
else if (ft_strchr(&s[1], '\"')) else if (ft_strchr(&s[1], '\"')) // if closed quotes
*quote_state = IN_DQUOTES; *quote_state = IN_DQUOTES;
else else
return (0); return (0);

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/13 04:35:06 by lperrey #+# #+# */ /* Created: 2021/11/13 04:35:06 by lperrey #+# #+# */
/* Updated: 2021/12/20 16:29:27 by hulamy ### ########.fr */ /* Updated: 2021/11/26 21:27:05 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -44,7 +44,7 @@ static int quote_state_change(int *quote_state, const char *s)
{ {
if (*quote_state == IN_QUOTES) if (*quote_state == IN_QUOTES)
*quote_state = 0; *quote_state = 0;
else if (ft_strchr(&s[1], '\'')) else if (ft_strchr(&s[1], '\'')) // if closed quotes
*quote_state = IN_QUOTES; *quote_state = IN_QUOTES;
else else
return (0); return (0);
@@ -54,7 +54,7 @@ static int quote_state_change(int *quote_state, const char *s)
{ {
if (*quote_state == IN_DQUOTES) if (*quote_state == IN_DQUOTES)
*quote_state = 0; *quote_state = 0;
else if (ft_strchr(&s[1], '\"')) else if (ft_strchr(&s[1], '\"')) // if closed quotes
*quote_state = IN_DQUOTES; *quote_state = IN_DQUOTES;
else else
return (0); return (0);

62
srcs/init/handle_argv.c Normal file
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);
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */ /* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/22 19:24:04 by lperrey ### ########.fr */ /* Updated: 2021/12/18 14:22:20 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,8 +14,7 @@
void init_readline(void); void init_readline(void);
int init_shlvl(void); int init_shlvl(void);
void open_script_file(t_all *c, char *argv[]); int handle_argv(t_all *c, char *argv[]);
int init_prompt(t_all *c, int script_fd);
int init(t_all *c, char *argv[]) int init(t_all *c, char *argv[])
{ {
@@ -25,11 +24,10 @@ int init(t_all *c, char *argv[])
environ = ft_dup_2d_arr(environ, (t_dup_f)ft_strdup); environ = ft_dup_2d_arr(environ, (t_dup_f)ft_strdup);
if (!environ) if (!environ)
return (ft_reti_perror(0, "ft_dup_2d_arr(environ)")); return (ft_reti_perror(0, "ft_dup_2d_arr(environ)"));
retrieve_path(&c->path); c->path = retrieve_path();
if (!init_shlvl()) if (!init_shlvl())
return (ft_reti_perror(0, "init_shlvl()")); return (ft_reti_perror(0, "init_shlvl()"));
open_script_file(c, argv); if (!handle_argv(c, argv))
if (!init_prompt(c, c->script_fd)) return (0);
return (ft_reti_perror(0, "init_prompt()"));
return (1); return (1);
} }

View File

@@ -6,29 +6,13 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */ /* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:25:46 by lperrey ### ########.fr */ /* Updated: 2021/12/18 12:33:50 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
static char *init_prompt_base(void); char *init_prompt_base(void)
int init_prompt(t_all *c, int script_fd)
{
if (!script_fd && isatty(STDIN_FILENO))
{
c->prompt_base = init_prompt_base();
if (!c->prompt_base)
return (0);
c->prompt = update_prompt(c->prompt_base);
if (!c->prompt)
return (0);
}
return (1);
}
static char *init_prompt_base(void)
{ {
char *prompt_base; char *prompt_base;
char *tmp; char *tmp;
@@ -56,7 +40,7 @@ static char *init_prompt_base(void)
return (prompt_base); return (prompt_base);
} }
char *update_prompt(char *prompt_base) char *init_prompt(char *prompt_base)
{ {
char *prompt; char *prompt;

View File

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

View File

@@ -6,14 +6,12 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */ /* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
/* Updated: 2021/12/20 22:26:14 by lperrey ### ########.fr */ /* Updated: 2021/12/18 05:08:48 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int g_switch_heredoc_sigint;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
t_all c; t_all c;
@@ -21,10 +19,8 @@ int main(int argc, char *argv[])
(void)argc; (void)argc;
if (!init(&c, argv)) if (!init(&c, argv))
exit_free(&c, EXIT_FAILURE); exit_free(&c, EXIT_FAILURE);
if (c.script_fd) if (!isatty(STDIN_FILENO))
shell_script(&c, c.script_fd); shell_script(&c);
else if (!isatty(STDIN_FILENO))
shell_script(&c, STDIN_FILENO);
else else
shell_loop(&c); shell_loop(&c);
return (0); return (0);

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */ /* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
/* Updated: 2021/12/21 12:14:43 by lperrey ### ########.fr */ /* Updated: 2021/12/18 14:15:13 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -20,16 +20,7 @@ int exit_free(t_all *c, int exit_status)
ft_free_2d_arr(environ); ft_free_2d_arr(environ);
ft_free_2d_arr(c->path); ft_free_2d_arr(c->path);
free_pipeline(&c->pipeline); free_pipeline(&c->pipeline);
if (c->script_fd) if (!isatty(STDIN_FILENO))
{
if (c->script_fd > 0)
{
gnl(c->script_fd, NULL, 1);
if (close(c->script_fd) == -1)
perror("close()");
}
}
else if (!isatty(STDIN_FILENO))
gnl(STDIN_FILENO, NULL, 1); gnl(STDIN_FILENO, NULL, 1);
else else
rl_clear_history(); rl_clear_history();
@@ -66,27 +57,22 @@ void close_pipeline_fd(t_cmd *pipeline[])
i = 0; i = 0;
while (pipeline[i]) while (pipeline[i])
{ {
close_cmd_fd(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++; i++;
} }
} }
void close_cmd_fd(t_cmd *cmd)
{
if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0)
{
if (close(cmd->fd_in) == -1)
perror("close()");
cmd->fd_in = 0;
}
if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0)
{
if (close(cmd->fd_out) == -1)
perror("close()");
cmd->fd_out = 0;
}
}
void close_stdio(void) void close_stdio(void)
{ {
if (close(STDIN_FILENO) == -1) if (close(STDIN_FILENO) == -1)

View File

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

View File

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

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/23 18:56:53 by lperrey #+# #+# */ /* Created: 2021/10/23 18:56:53 by lperrey #+# #+# */
/* Updated: 2021/12/18 14:21:47 by lperrey ### ########.fr */ /* Updated: 2021/12/19 12:11:14 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

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

View File

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

View File

@@ -6,14 +6,15 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/21 01:12:42 by lperrey ### ########.fr */ /* Updated: 2021/12/16 14:51:33 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
t_list *content_copy(char *content, int *i, int *quotes_state); static t_list *content_copy(char *content, int *i, int *quotes_state);
t_list *content_expand(char *content, int *i); static t_list *content_expand(char *content, int *i);
static char *env_var_expansion(char *content, int *i);
t_list *expand_token(char *content) t_list *expand_token(char *content)
{ {
@@ -34,10 +35,101 @@ t_list *expand_token(char *content)
expand->next = content_copy(content, &i, &quotes_state); expand->next = content_copy(content, &i, &quotes_state);
expand = expand->next; expand = expand->next;
if (!expand) if (!expand)
{ {//todo wrap
perror("expand_token() error"); perror("expand_token() error");
return (ft_lstclear(&head.next, free)); return (ft_lstclear(&head.next, free));
} }
} }
return (head.next); 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
*/

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/20 15:51:18 by hulamy ### ########.fr */ /* Updated: 2021/12/16 14:50:58 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -16,24 +16,19 @@ t_list *expand_token(char *content);
char *rejoin_after_expand(t_list *expand_lst); char *rejoin_after_expand(t_list *expand_lst);
int new_token_for_each_field(char **fields, t_token *t); int new_token_for_each_field(char **fields, t_token *t);
/* // 1 - chaque bout dans un element d'une t_list
* 1 - chaque bout dans un element d'une t_list // (telle quelle si non expand, ou VARIABLE de env)
* (telle quelle si non expand, ou VARIABLE de env) // 2 - strjoin() le tout
* 2 - strjoin() le tout // 3 - split avec un ft_strplit() modifié (ne splitant pas dans les quotes)
* 3 - split avec un ft_strplit() modifié (ne splitant pas dans les quotes) // 4 - quotes removal, ft_strdup_quotes() le tableau split
* 4 - quotes removal, ft_strdup_quotes() le tableau split // 5 - creer un token T_WORD pour chaque *string du **split_arr
* 5 - creer un token T_WORD pour chaque *string du **split_arr // (ft_lstadd_front() sur le token original, puis set le token orignal à :
* (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)
* 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 expansions(t_token *t, t_cmd **pipeline)
{ {
int i; int i;
t_token *next_token; t_token *next_token;
i = 0; i = 0;
while (t) while (t)
@@ -61,21 +56,26 @@ int token_expansions(t_token *t)
void *tmp; void *tmp;
char **tmp_split; char **tmp_split;
tmp = (t_list *)expand_token(t->content); // 1
tmp = (t_list*)expand_token(t->content);
if (!tmp) if (!tmp)
return (0); return (0);
tmp = (char *)rejoin_after_expand(tmp); // 2
tmp = (char*)rejoin_after_expand(tmp);
if (!tmp) if (!tmp)
return (0); return (0);
// 3
tmp_split = ft_split_quotes(tmp, ' '); tmp_split = ft_split_quotes(tmp, ' ');
free(tmp); free(tmp);
if (!tmp_split) if (!tmp_split)
return (0); return (0);
// 4
tmp = tmp_split; tmp = tmp_split;
tmp_split = ft_dup_2d_arr(tmp_split, (t_dup_f)ft_strdup_quotes); tmp_split = ft_dup_2d_arr(tmp_split, (t_dup_f)ft_strdup_quotes);
ft_free_2d_arr(tmp); ft_free_2d_arr(tmp);
if (!tmp_split) if (!tmp_split)
return (0); return (0);
// 5
if (!new_token_for_each_field(tmp_split, t)) if (!new_token_for_each_field(tmp_split, t))
return (0); return (0);
return (1); return (1);

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/20 17:22:41 by hulamy ### ########.fr */ /* Updated: 2021/12/16 14:50:36 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -28,11 +28,10 @@ int new_token_for_each_field(char **fields, t_token *t)
insert_lst->next = ft_lstnew_generic(sizeof(t_token), 0); insert_lst->next = ft_lstnew_generic(sizeof(t_token), 0);
insert_lst = insert_lst->next; insert_lst = insert_lst->next;
if (!insert_lst) if (!insert_lst)
{ {//todo wrap
perror("insert_token_for_each_field() error"); perror("insert_token_for_each_field() error");
ft_free_2d_arr(fields); ft_free_2d_arr(fields);
ft_lstclear((t_list **)&head.next, NULL); return ((int)ft_lstclear((t_list **)&head.next, NULL));
return (0);
} }
insert_lst->content = fields[i]; insert_lst->content = fields[i];
insert_lst->id = T_WORD; insert_lst->id = T_WORD;
@@ -52,8 +51,11 @@ static void insert_tokens(t_token *t, t_token *insert_lst)
ft_free_null(&t->content); ft_free_null(&t->content);
if (!insert_lst) if (!insert_lst)
return ; return ;
tmp = t->next; tmp = t->next;
t->next = insert_lst; t->next = insert_lst;
insert_lst_last = (t_token *)ft_lstlast((t_list *)insert_lst); insert_lst_last = (t_token *)ft_lstlast((t_list *)insert_lst);
insert_lst_last->next = tmp; insert_lst_last->next = tmp;
//return (insert_lst_last); // return inutile pour reusinage
} }

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */ /* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
/* Updated: 2021/12/20 14:55:03 by hulamy ### ########.fr */ /* Updated: 2021/11/07 04:03:02 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -23,9 +23,9 @@ char *rejoin_after_expand(t_list *expand_lst)
{ {
result = ft_strjoinfree_s1(result, expand_lst->content); result = ft_strjoinfree_s1(result, expand_lst->content);
if (!result) if (!result)
{ {//todo wrap
perror("rejoin_after_expand() error"); perror("rejoin_after_expand() error");
return (ft_lstclear(&head, free)); return (ft_lstclear(&head, free));
} }
expand_lst = expand_lst->next; expand_lst = expand_lst->next;
} }

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */ /* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */
/* Updated: 2021/12/22 13:53:19 by lperrey ### ########.fr */ /* Updated: 2021/12/17 17:45:25 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,20 +14,26 @@
void save_redirections_words(t_token *t); void save_redirections_words(t_token *t);
t_cmd **parsing(t_token *token_list, int script_fd) t_cmd **parsing(t_token *token_list)
{ {
t_cmd **pipeline; t_cmd **pipeline;
if (!valid_syntax(token_list)) if (!valid_syntax(token_list))
return (NULL); return (NULL);
// 2.9.1 - 1) Save Words
save_redirections_words(token_list); save_redirections_words(token_list);
// Struct CMD alloc
pipeline = pipeline_alloc(1 + count_pipes(token_list)); pipeline = pipeline_alloc(1 + count_pipes(token_list));
if (!pipeline) if (!pipeline)
return (NULL); return (NULL);
// 2.9.1 - 2) Expansion
if (!expansions(token_list, pipeline)) if (!expansions(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline)); return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
if (!redirections(token_list, pipeline, script_fd)) // 2.9.1 - 3) Redirection
if (!redirections(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline)); return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
// Struct CMD fill
if (!pipeline_fill_argv(token_list, pipeline)) if (!pipeline_fill_argv(token_list, pipeline))
return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline)); return (ft_retp_free(NULL, &pipeline, (t_free_f)free_pipeline));
return (pipeline); return (pipeline);
@@ -38,7 +44,7 @@ void save_redirections_words(t_token *t)
while (t) while (t)
{ {
if (t->id == '>' || t->id == T_DGREAT if (t->id == '>' || t->id == T_DGREAT
|| t->id == '<' || t->id == T_DLESS) || t->id == '<' || t->id == T_DLESS)
{ {
t = t->next; t = t->next;
t->id = T_REDIRECTION_WORD; t->id = T_REDIRECTION_WORD;

View File

@@ -6,21 +6,21 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */ /* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/12/22 17:04:47 by lperrey ### ########.fr */ /* Updated: 2021/12/19 12:12:27 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
static int here_doc_write(char *delimiter, int doc_fd, int script_fd); 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_interactive(char *delimiter, int doc_fd);
static int here_doc_write_script(char *delimiter, int doc_fd, int script_fd); static int here_doc_write_script(char *delimiter, int doc_fd);
static int event_hook_empty(void); static int event_hook_empty(void);
#define TMP_HERE_DOC "/tmp/minishell_here_doc" #define TMP_HERE_DOC "/tmp/minishell_here_doc"
#define WARNING_EOF "warning: here-document delimited by end-of-file (wanted `" #define WARNING_EOF "warning: here-document delimited by end-of-file (wanted `"
int here_doc(char *delimiter, int script_fd) int here_doc(char *delimiter)
{ {
int here_doc; int here_doc;
int ret; int ret;
@@ -31,7 +31,7 @@ int here_doc(char *delimiter, int script_fd)
here_doc = open(TMP_HERE_DOC, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); here_doc = open(TMP_HERE_DOC, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (here_doc == -1) if (here_doc == -1)
return (ft_reti_perror_io(-1, "open() ", TMP_HERE_DOC)); return (ft_reti_perror_io(-1, "open() ", TMP_HERE_DOC));
ret = here_doc_write(delimiter, here_doc, script_fd); ret = here_doc_write(delimiter, here_doc);
free(delimiter); free(delimiter);
if (close(here_doc) == -1) if (close(here_doc) == -1)
shell_perror(TMP_HERE_DOC, ": ", "", 0); shell_perror(TMP_HERE_DOC, ": ", "", 0);
@@ -49,16 +49,12 @@ int here_doc(char *delimiter, int script_fd)
return (here_doc); return (here_doc);
} }
static int here_doc_write(char *delimiter, int doc_fd, int script_fd) static int here_doc_write(char *delimiter, int doc_fd)
{ {
int ret; int ret;
struct sigaction signal_action; struct sigaction signal_action;
if (script_fd || !isatty(STDIN_FILENO)) if (isatty(STDIN_FILENO))
{
ret = here_doc_write_script(delimiter, doc_fd, script_fd);
}
else
{ {
ft_bzero(&signal_action, sizeof(signal_action)); ft_bzero(&signal_action, sizeof(signal_action));
signal_action.sa_handler = sigint_handler_heredoc; signal_action.sa_handler = sigint_handler_heredoc;
@@ -69,13 +65,16 @@ static int here_doc_write(char *delimiter, int doc_fd, int script_fd)
signal_action.sa_handler = SIG_IGN; signal_action.sa_handler = SIG_IGN;
sigaction(SIGINT, &signal_action, NULL); sigaction(SIGINT, &signal_action, NULL);
} }
else
{
ret = here_doc_write_script(delimiter, doc_fd);
}
return (ret); return (ret);
} }
static int here_doc_write_interactive(char *delimiter, int doc_fd) static int here_doc_write_interactive(char *delimiter, int doc_fd)
{ {
char *line; char *line;
size_t line_len;
line = NULL; line = NULL;
g_switch_heredoc_sigint = 0; g_switch_heredoc_sigint = 0;
@@ -86,10 +85,9 @@ static int here_doc_write_interactive(char *delimiter, int doc_fd)
return (set_last_exit_status(EXIT_SIGNAL + SIGINT)); return (set_last_exit_status(EXIT_SIGNAL + SIGINT));
if (!line) if (!line)
return (shell_error(WARNING_EOF, delimiter, "')", 0)); return (shell_error(WARNING_EOF, delimiter, "')", 0));
line_len = ft_strlen(line); 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.
if (ft_strncmp(line, delimiter, line_len + 1) == 0)
break ; break ;
if (write(doc_fd, line, line_len) == -1) if (write(doc_fd, line, ft_strlen(line)) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
if (write(doc_fd, "\n", 1) == -1) if (write(doc_fd, "\n", 1) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
@@ -99,23 +97,21 @@ static int here_doc_write_interactive(char *delimiter, int doc_fd)
return (0); return (0);
} }
static int here_doc_write_script(char *delimiter, int doc_fd, int script_fd) static int here_doc_write_script(char *delimiter, int doc_fd)
{ {
char *line; char *line;
int ret; int ret;
size_t line_len;
line = NULL; line = NULL;
ret = 1; ret = 1;
while (ret) while (ret)
{ {
ret = gnl(script_fd, &line, 0); ret = gnl(STDIN_FILENO, &line, 0);
if (ret == -1) if (ret == -1)
return (ft_reti_perror_free(-1, line, free, "gnl() script_fd")); return (ft_reti_perror_free(-1, line, free, "gnl() STDIN"));
line_len = ft_strlen(line); 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.
if (ft_strncmp(line, delimiter, line_len + 1) == 0)
break ; break ;
if (write(doc_fd, line, line_len) == -1) if (write(doc_fd, line, ft_strlen(line)) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));
if ((ret || line[0]) && write(doc_fd, "\n", 1) == -1) if ((ret || line[0]) && write(doc_fd, "\n", 1) == -1)
return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC));

View File

@@ -6,20 +6,19 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */ /* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/12/22 14:00:33 by lperrey ### ########.fr */ /* Updated: 2021/12/16 14:49:28 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
int here_doc(char *delimiter, int script_fd); int here_doc(char *delimiter);
static int redirect_cmd_input(t_token *t, t_cmd *cmd); static int redirect_cmd_input(t_token *t, t_cmd *cmd);
static int redirect_cmd_heredoc(t_token *t, t_cmd *cmd, int script_fd);
static int redirect_cmd_output(t_token *t, t_cmd *cmd); static int redirect_cmd_output(t_token *t, t_cmd *cmd);
static int expand_redirection(t_token *t); static int expand_redirection(t_token *t);
int redirections(t_token *t, t_cmd **pipeline, int script_fd) int redirections(t_token *t, t_cmd **pipeline)
{ {
int i; int i;
@@ -30,14 +29,16 @@ int redirections(t_token *t, t_cmd **pipeline, int script_fd)
i++; i++;
if (!pipeline[i]->error) if (!pipeline[i]->error)
{ {
if (t->id == '<' && !redirect_cmd_input(t, pipeline[i])) if (t->id == '<' || t->id == T_DLESS)
return (0); {
else if (t->id == T_DLESS if (!redirect_cmd_input(t, pipeline[i]))
&& !redirect_cmd_heredoc(t, pipeline[i], script_fd)) return (0);
return (0); }
else if (t->id == '>' || t->id == T_DGREAT) else if (t->id == '>' || t->id == T_DGREAT)
{
if (!redirect_cmd_output(t, pipeline[i])) if (!redirect_cmd_output(t, pipeline[i]))
return (0); return (0);
}
} }
t = t->next; t = t->next;
} }
@@ -49,35 +50,33 @@ static int redirect_cmd_input(t_token *t, t_cmd *cmd)
if (cmd->fd_in != STDIN_FILENO) if (cmd->fd_in != STDIN_FILENO)
if (close(cmd->fd_in) == -1) if (close(cmd->fd_in) == -1)
perror("close()"); perror("close()");
if (!expand_redirection(t)) if (t->id == '<')
{ {
cmd->error = EXIT_REDIRECTION; if (!expand_redirection(t))
return (1); {
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;
}
} }
cmd->fd_in = open(t->next->content, O_RDONLY); else if (t->id == T_DLESS)
if (cmd->fd_in == -1)
{ {
shell_perror(t->next->content, ": ", "", 0); cmd->fd_in = here_doc(t->next->content);
cmd->error = EXIT_REDIRECTION; if (cmd->fd_in == -1)
} {
return (1); shell_error("heredoc error", ": ", "", 0);
} cmd->error = EXIT_REDIRECTION;
}
static int redirect_cmd_heredoc(t_token *t, t_cmd *cmd, int script_fd) else if (cmd->fd_in > EXIT_SIGNAL)
{ {
if (cmd->fd_in != STDIN_FILENO) cmd->fd_in = 0;
if (close(cmd->fd_in) == -1) return (0);
perror("close()"); }
cmd->fd_in = here_doc(t->next->content, script_fd);
if (cmd->fd_in == -1)
{
shell_error("heredoc error", ": ", "", 0);
cmd->error = EXIT_REDIRECTION;
}
else if (cmd->fd_in > EXIT_SIGNAL)
{
cmd->fd_in = 0;
return (0);
} }
return (1); return (1);
} }
@@ -91,7 +90,7 @@ static int redirect_cmd_output(t_token *t, t_cmd *cmd)
perror("close()"); perror("close()");
if (!expand_redirection(t)) if (!expand_redirection(t))
{ {
cmd->error = EXIT_REDIRECTION; cmd->error = EXIT_REDIRECTION;
return (1); return (1);
} }
flags = O_WRONLY | O_CREAT; flags = O_WRONLY | O_CREAT;
@@ -111,7 +110,7 @@ static int redirect_cmd_output(t_token *t, t_cmd *cmd)
static int expand_redirection(t_token *t) static int expand_redirection(t_token *t)
{ {
t_token *head; t_token *head;
t_token *next_token; t_token *next_token;
int ret; int ret;
ret = 1; ret = 1;
@@ -127,7 +126,7 @@ static int expand_redirection(t_token *t)
head->next = t->next; head->next = t->next;
free(t); free(t);
if (head->next) if (head->next)
head->next->id = T_REDIRECTION_WORD; head->next->id = T_REDIRECTION_WORD; // Eventuellement a integrer dans token_expansions()
if (ft_lstsize((t_list *)head->next) != 1) if (ft_lstsize((t_list *)head->next) != 1)
{ {
ret = 0; ret = 0;

View File

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

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */ /* Created: 2021/10/24 18:52:05 by lperrey #+# #+# */
/* Updated: 2021/12/22 20:19:08 by lperrey ### ########.fr */ /* Updated: 2021/12/17 03:28:53 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -37,6 +37,5 @@ int valid_command(t_token **token_list)
*token_list = cmd_start; *token_list = cmd_start;
if (valid_command_rule5(token_list)) if (valid_command_rule5(token_list))
return (1); return (1);
*token_list = cmd_start;
return (0); return (0);
} }

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */ /* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
/* Updated: 2021/12/22 13:56:38 by lperrey ### ########.fr */ /* Updated: 2021/12/18 12:34:08 by hulamy ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -30,7 +30,7 @@ void shell_loop(t_all *c)
ft_free_null(&line_input); ft_free_null(&line_input);
if (!c->token_list) if (!c->token_list)
continue ; continue ;
c->pipeline = parsing(c->token_list, 0); c->pipeline = parsing(c->token_list);
ft_lstclear((t_list **)&c->token_list, free); ft_lstclear((t_list **)&c->token_list, free);
if (!c->pipeline) if (!c->pipeline)
continue ; continue ;

View File

@@ -6,16 +6,16 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/26 23:47:44 by lperrey #+# #+# */ /* Created: 2021/10/26 23:47:44 by lperrey #+# #+# */
/* Updated: 2021/12/22 14:01:52 by lperrey ### ########.fr */ /* Updated: 2021/12/18 15:15:30 by lperrey ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "minishell.h" #include "minishell.h"
static char *read_input_script(t_all *c, int script_fd); static char *read_input_script(t_all *c);
static void exit_signal(t_all *c); static void exit_signal(t_all *c);
void shell_script(t_all *c, int script_fd) void shell_script(t_all *c)
{ {
char *line_input; char *line_input;
@@ -23,7 +23,7 @@ void shell_script(t_all *c, int script_fd)
while (1) while (1)
{ {
free(line_input); free(line_input);
line_input = read_input_script(c, script_fd); line_input = read_input_script(c);
if (!line_input) if (!line_input)
break ; break ;
if (line_input && *line_input) if (line_input && *line_input)
@@ -32,7 +32,7 @@ void shell_script(t_all *c, int script_fd)
ft_free_null(&line_input); ft_free_null(&line_input);
if (!c->token_list) if (!c->token_list)
break ; break ;
c->pipeline = parsing(c->token_list, script_fd); c->pipeline = parsing(c->token_list);
ft_lstclear((t_list **)&c->token_list, free); ft_lstclear((t_list **)&c->token_list, free);
if (!c->pipeline) if (!c->pipeline)
break ; break ;
@@ -44,7 +44,7 @@ void shell_script(t_all *c, int script_fd)
exit_free(c, get_last_exit_status()); exit_free(c, get_last_exit_status());
} }
static char *read_input_script(t_all *c, int script_fd) static char *read_input_script(t_all *c)
{ {
char *line_input; char *line_input;
struct sigaction signal_behaviour; struct sigaction signal_behaviour;
@@ -54,7 +54,7 @@ static char *read_input_script(t_all *c, int script_fd)
signal_behaviour.sa_handler = SIG_IGN; signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGINT, &signal_behaviour, NULL); sigaction(SIGINT, &signal_behaviour, NULL);
line_input = NULL; line_input = NULL;
ret = gnl(script_fd, &line_input, 0); ret = gnl(STDIN_FILENO, &line_input, 0);
if (ret == -1) if (ret == -1)
{ {
free(line_input); free(line_input);

View File

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

13
trap Normal file
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