+ readline() replace gnl() in here_doc
+ "int error" in struct "t_cmd"
This commit is contained in:
LuckyLaszlo
2021-11-16 22:30:20 +01:00
17 changed files with 378 additions and 208 deletions

View File

@@ -24,7 +24,7 @@ LIBFT_D = ./libft
LIBFT = $(LIBFT_D)/libft.a
SRCS = main.c init.c free.c generic.c \
signals.c terminal.c \
signals.c \
shell_loop.c shell_script.c \
lexing.c fill_token.c check_operators.c \
parsing.c cmd_array.c \
@@ -33,7 +33,7 @@ SRCS = main.c init.c free.c generic.c \
ft_split_quotes.c ft_strdup_quotes.c \
redirections.c here_doc.c \
exec_cmd_line.c \
env.c exit.c echo.c
cd.c pwd.c export.c unset.c exit.c env.c echo.c
DIR_OBJS = builds
OBJS = $(SRCS:%.c=$(DIR_OBJS)/%.o)

153
README.md
View File

@@ -1,18 +1,50 @@
## understanding some things :
- [how to send EOF to stdin of a shell 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/)
- [really handling process](https://stackoverflow.com/questions/47489128/handling-signals-sigstp-sigcont-sigint-with-child-process)
- [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)
- commande utile pour tester les process parents et enfants : while true ; do ps -o pid,pgid,cmd -C bash ; sleep 0.1 ; echo "\n" ; done
```text
| BASH | MINISHELL |
-----------------------------------
| print | action | print | action |
---------------|-----------------|----------------|----------------|
| SIGINT / ctrl-C | ^C | \n | ^C | exit |
prompt> |-----------------|----------------|----------------|
| EOF / ctrl-D | exit | exit | Ø | \n |
---------------|-----------------|----------------|----------------|
| SIGINT / ctrl-C | bla^C | \n | bla^C | exit |
prompt> blabla |-----------------|----------------|----------------|
| EOF / ctrl-D | Ø | Ø | Ø | Ø |
---------------|-----------------|----------------|----------------|
-> change signal handler for SIGINT, to print a \n instead of exit
-> change when readline receive an EOF and line is empty, to print exit and exit
-> when readline receive an EOF and line is empty, it return NULL
-> if line isn't empty it does nothing
```
## 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)
- [2. external functions :](#markdown-header-2-external-functions)
- [3. parsing :](#markdown-header-3-parsing)
- [3.1. methode arbre binaire :](#markdown-header-31-methode-arbre-binaire)
- [4. gerer les quotes et la separation des arguments :](#markdown-header-4-gerer-les-quotes-et-la-separation-des-arguments)
- [4.1. tentative methode 1 :](#markdown-header-41-tentative-methode-1)
- [4.1.1. pseudo code :](#markdown-header-411-pseudo-code)
- [4.1.2. application :](#markdown-header-412-application)
- [4.1.3. erreur :](#markdown-header-413-erreur)
- [4.2. tentative methode 2 :](#markdown-header-42-tentative-methode-2)
- [4.2.1. deroulement :](#markdown-header-421-deroulement)
- [4.2.2. application :](#markdown-header-422-application)
- [4.3. comportement reel chelou :](#markdown-header-43-comportement-reel-chelou)
- [5. notes :](#markdown-header-5-notes)
## 1. todo list :
---
@@ -56,10 +88,83 @@
*[\go to sommaire](#markdown-header-sommaire)*
## 2. parsing :
## 2. 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
- **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()
*[\go to sommaire](#markdown-header-sommaire)*
## 3. parsing :
---
### 2.1 methode arbre binaire :
### 3.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)
@@ -93,12 +198,12 @@ EXEMPLE : . .
*[\go to sommaire](#markdown-header-sommaire)*
## 3. gerer les quotes et la separation des arguments :
## 4. gerer les quotes et la separation des arguments :
---
### 3.1 tentative methode 1 :
### 4.1 tentative methode 1 :
#### 3.1.1 pseudo code :
#### 4.1.1 pseudo code :
```text
q = 0 // first quote
c = 0 // count
@@ -147,7 +252,7 @@ while (str[i])
*[\go to sommaire](#markdown-header-sommaire)*
#### 3.1.2 application :
#### 4.1.2 application :
```text
['][a][r][g][1][ ]['][a][r][g][2]["][ ][a][r][g][3]["]
c = 0 . . . . . . . . . . . . . . . . . .
@@ -190,7 +295,7 @@ c = . . . . . . . . . 0 str[i] != ' | " ; ->
*[\go to sommaire](#markdown-header-sommaire)*
#### 3.1.3 erreur :
#### 4.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" !
@@ -198,9 +303,9 @@ c = . . . . . . . . . 0 str[i] != ' | " ; ->
*[\go to sommaire](#markdown-header-sommaire)*
### 3.2 tentative methode 2 :
### 4.2 tentative methode 2 :
#### 3.2.1 deroulement :
#### 4.2.1 deroulement :
```text
.--------------------------------------------.
: .--------------------------------------. :
@@ -228,7 +333,7 @@ c = . . . . . . . . . 0 str[i] != ' | " ; ->
*[\go to sommaire](#markdown-header-sommaire)*
#### 3.2.2 application :
#### 4.2.2 application :
```text
.--.
1 : '__"__'__"__"__"__'__'__"__"__'__'__"__'__"__'
@@ -258,7 +363,7 @@ c = . . . . . . . . . 0 str[i] != ' | " ; ->
*[\go to sommaire](#markdown-header-sommaire)*
### 3.3 comportement reel chelou :
### 4.3 comportement reel chelou :
```text
echo "_"
_
@@ -303,7 +408,7 @@ _'___"___'___"_"___'___"___'_
*[\go to sommaire](#markdown-header-sommaire)*
## 4. notes :
## 5. notes :
---
Ordre Interpreteur :

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:59:58 by lperrey #+# #+# */
/* Updated: 2021/11/16 08:04:08 by lperrey ### ########.fr */
/* Updated: 2021/11/16 21:06:00 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -16,11 +16,10 @@
// Init
int init(t_all *c, char *envp[]);
char **retrieve_path(char *envp[]);
int set_signals_handling(struct sigaction *ori_signal_behaviour,
struct sigaction *signal_behaviour);
int set_terminal_attributes(struct termios *ori_termios,
struct termios *interactive_termios,
int *termios_changed);
int *termios_changed); // WIP, TEST, TEMP, PLACEHOLDER, NOT IMPORTANT, :)
int set_signals_handling(struct sigaction *signal_behaviour);
// Shell modes
void shell_loop(t_all *c);
@@ -45,9 +44,14 @@ int redirections(t_token *token_list, t_cmd **cmd_arr);
int exec_cmd_line(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 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);
int getenv_position(char **envp, char *name);
// Free
int free_exit(t_all *c, int exit_status);
@@ -75,4 +79,8 @@ int ft_reti_perror_io(int ret, char *err_str, char *io_file);
char **ft_split_quotes(char const *s, char c);
char *ft_strdup_quotes(const char *s);
// signals.c
void sigint_handler_interactiv(int signum);
void sigint_handler_execution(int signum);
#endif

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 02:35:52 by lperrey #+# #+# */
/* Updated: 2021/11/16 08:45:10 by lperrey ### ########.fr */
/* Updated: 2021/11/16 21:38:28 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -46,6 +46,7 @@ typedef struct s_cmd
int fd_in;
int fd_out;
pid_t pid;
int error;
} t_cmd;
typedef struct s_all
@@ -57,10 +58,10 @@ typedef struct s_all
char *prompt;
t_token *token_list;
int last_exit_status;
struct termios ori_termios;
struct termios interactive_termios;
int termios_changed;
struct sigaction ori_signal_behaviour;
// struct termios ori_termios;
// struct termios interactive_termios;
// int termios_changed;
// struct sigaction ori_signal_behaviour;
struct sigaction signal_behaviour;
} t_all;

View File

@@ -1,77 +0,0 @@
#include "minishell.h"
void close_fd(t_cmd *cmd)
{
if (cmd->fd_in != 0)
close(cmd->fd_in);
if (cmd->fd_out != 1)
close(cmd->fd_out);
}
void execute_cmd(char **envp, t_cmd **cmd_arr)
{
pid_t pid;
pid_t wpid;
int status;
int i;
i = 0;
while(cmd_arr[i])
{
pid = fork();
if (pid == 0)
{
if (cmd_arr[i]->fd_in != 0)
dup2(cmd_arr[i]->fd_in, STDIN_FILENO);
if (cmd_arr[i]->fd_out != 1)
dup2(cmd_arr[i]->fd_out, STDOUT_FILENO);
//close_fd(cmd_arr[i]);
//Must close all fds, not just the two cmd_arr[i] fd
execve(cmd_arr[i]->argv[0], cmd_arr[i]->argv, envp);
}
else
close_fd(cmd_arr[i]); // Close here or after all execve() for simplicity ?
i++;
}
// waitpid pour la derniere commande (pour '$?')
while ((wpid = wait(&status)) > 0);
}
/*
int handle_fdd(char *input, int fdin, t_cmd *cmd)
{
int *pipes_fd;
int next_in;
char *tmp;
cmd->fd_in = fdin;
cmd->fd_out = 1;
next_in = 0;
if (input + 1)
{
pipes_fd = calloc(2, sizeof(int));
pipe(pipes_fd);
cmd->fd_out = pipes_fd[1];
next_in = pipes_fd[0];
}
tmp = ft_strchr(input, '>');
if (tmp)
{
tmp[0] = '\0';
tmp = ft_strtrim(tmp + 2, " "); // +2 for "> "
if (cmd->fd_out != 1)
close(cmd->fd_out);
cmd->fd_out = open(tmp, O_RDWR | O_TRUNC);
}
tmp = ft_strchr(input, '<');
if (tmp)
{
tmp[0] = '\0';
tmp = ft_strtrim(tmp + 2, " "); // +2 for "> "
if (cmd->fd_in != 0)
close(cmd->fd_in);
cmd->fd_in = open(tmp, O_RDONLY);
}
printf(" handle_fd: %s\n", input);
return (next_in);
} */

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

@@ -0,0 +1,10 @@
#include "minishell.h"
int builtin_cd(int argc, char *argv[], t_all *c)
{
(void)argc;
(void)c;
chdir(argv[1]);
return (0);
}

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

@@ -0,0 +1,50 @@
#include "minishell.h"
int getenv_position(char **envp, char *name)
{
int i;
i = 0;
while (envp[i] && ft_strncmp(envp[i], name, ft_strlen(name)))
i++;
if (!envp[i])
return (-1);
return (i);
}
int builtin_export(int argc, char *argv[], t_all *c)
{
char **var;
int position;
(void)argc;
var = ft_split(argv[1], '=');
position = getenv_position(c->envp, var[0]);
if (position == -1 || !ft_strchr(argv[1], '='))
{
ft_free_2d_arr(var);
return (0);
}
c->envp[position] = ft_strjoin(var[0], "=");
if (var[1]) // parce que ft_strjoin return NULL si var[1] est null, pourquoi ?
c->envp[position] = ft_strjoinfree_s1(c->envp[position], var[1]);
ft_free_2d_arr(var);
return (0);
}
/*
** comportement de bash :
** 1. modifier une variable dans bash :
** > ca ne la modifie pas dans zsh
** > ca ne la garde pas apres exit de bash
** 2. ajouter une variable dans bash :
** > ca ne la modifie pas dans zsh
** > ca ne la garde pas apres exit de bash
** 3. ajouter une variable avec erreur :
** > 'export VARIABLE' n'exporte rien
** > 'export VARIABLE=' exporte une variable vide
** 4. ordre d'insertion d'une nouvelle variable :
** > aucune idee
*/

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

@@ -0,0 +1,15 @@
#include "minishell.h"
int builtin_pwd(int argc, char *argv[], t_all *c)
{
char *pwd;
(void)argc;
(void)argv;
(void)c;
pwd = getcwd(NULL, 0);
write(1, pwd, ft_strlen(pwd));
write(1, "\n", 1);
return (0);
}

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

@@ -0,0 +1,23 @@
#include "minishell.h"
int builtin_unset(int argc, char *argv[], t_all *c)
{
int position;
(void)argc;
(void)c;
position = getenv_position(c->envp, argv[1]);
if (position == -1)
return (0);
while (c->envp[position])
{
write(1, "1", 1);
free(c->envp[position]);
c->envp[position] = ft_strdup(c->envp[position + 1]);
position++;
}
write(1, "2", 1);
free(c->envp[position]);
return (0);
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */
/* Updated: 2021/11/16 08:03:30 by lperrey ### ########.fr */
/* Updated: 2021/11/16 22:24:36 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -19,9 +19,8 @@ int free_exit(t_all *c, int exit_status)
ft_lstclear((t_list **)&c->token_list, free); // a voir avec Hugo, il y a un truc qui me semble superflu dans la fonction
ft_free_2d_arr(c->envp);
free_pipeline(&c->cmd_arr);
if (c->termios_changed)
tcsetattr(STDIN_FILENO, TCSANOW, &c->ori_termios);
gnl(STDIN_FILENO, NULL, 1);
//if (c->termios_changed)
// tcsetattr(STDIN_FILENO, TCSANOW, &c->ori_termios);
rl_clear_history();
exit(exit_status);
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */
/* Updated: 2021/11/16 03:45:10 by lperrey ### ########.fr */
/* Updated: 2021/11/16 21:06:18 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -30,13 +30,7 @@ int init(t_all *c, char *envp[])
c->prompt = init_prompt(c->prompt_base);
if (!c->prompt)
return (ft_reti_perror(0, "init_prompt() error"));
set_signals_handling(&c->ori_signal_behaviour, &c->signal_behaviour);
if (isatty(STDIN_FILENO))
{
if (!set_terminal_attributes(&c->ori_termios, &c->interactive_termios,
&c->termios_changed))
return (ft_reti_perror(0, "set_terminal_attributes() error"));
}
set_signals_handling(&c->signal_behaviour);
return (1);
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */
/* Updated: 2021/11/16 08:02:56 by lperrey ### ########.fr */
/* Updated: 2021/11/16 21:18:27 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -32,6 +32,7 @@ void save_redirections_words(t_token *t)
t = t->next;
}
}
void print_cmd_array(t_cmd **cmd_arr)
{
int i;

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/11/14 11:12:44 by lperrey ### ########.fr */
/* Updated: 2021/11/16 22:29:01 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -39,7 +39,6 @@ int here_doc(char *delimiter)
if (!here_doc_write(delimiter, here_doc))
{
free(delimiter);
gnl(STDIN_FILENO, NULL, 1);
return (0);
}
free(delimiter);
@@ -56,12 +55,24 @@ int here_doc(char *delimiter)
static int here_doc_write(char *delimiter, int doc_fd)
{
char *line;
size_t line_count;
line_count = 0;
while (1)
{
line_count++;
line = NULL;
if (gnl(STDIN_FILENO, &line, 0) == -1)
return (ft_reti_perror_free(0, line, free, "gnl() STDIN"));
line = readline("> ");
if (!line)
{ // TODO : error print wrapper
ft_putstr_fd("minishell: ", 2);
ft_putstr_fd("warning: here-document at line ", 2);
ft_putnbr_fd(line_count, 2);
ft_putstr_fd(" delimited by end-of-file (wanted `", 2);
ft_putstr_fd(delimiter, 2);
ft_putstr_fd("')\n", 2);
return (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)
@@ -71,7 +82,6 @@ static int here_doc_write(char *delimiter, int doc_fd)
free(line);
}
free(line);
gnl(STDIN_FILENO, NULL, 1);
return (1);
}

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
/* Updated: 2021/11/16 08:08:18 by lperrey ### ########.fr */
/* Updated: 2021/11/16 22:29:52 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
@@ -24,7 +24,7 @@ int redirections(t_token *t, t_cmd **cmd_arr)
i = 0;
while (t)
{
if (cmd_arr[i]->pid == 0) // Pid var as error mark, WIP
if (!cmd_arr[i]->error)
{
if (t->id == '<' || t->id == T_DLESS)
{
@@ -60,7 +60,7 @@ static int redirect_cmd_input(t_token *t, t_cmd *cmd)
if (cmd->fd_in == -1)
{
ft_perror_io("open() ", t->next->content); // todo error
cmd->pid = -1; // Pid var as error mark, WIP
cmd->error = 42; // WIP error status
}
}
else if (t->id == T_DLESS)
@@ -93,7 +93,7 @@ static int redirect_cmd_output(t_token *t, t_cmd *cmd)
if (cmd->fd_out == -1)
{
ft_perror_io("open() ", t->next->content);
cmd->pid = -1; // Pid var as error mark, WIP
cmd->error = 42; // WIP error status
}
return (1);
}

View File

@@ -6,18 +6,14 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/04 05:59:26 by lperrey #+# #+# */
/* Updated: 2021/11/16 03:52:37 by lperrey ### ########.fr */
/* Updated: 2021/11/16 21:22:32 by lperrey ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
//static char **tokens_list_to_argv(t_token *t); // temp test
void sigint_handler(int signum); //tmp
void sigquit_aka_eof_handler(int signum); //tmp
void close_fd(t_cmd *cmd);
void execute_cmd(char **envp, t_cmd **cmd_arr);
void execute_cmd(char **envp, t_cmd **cmd_arr, t_all *c);
void shell_loop(t_all *c)
{
@@ -45,11 +41,79 @@ void shell_loop(t_all *c)
exec_cmd_line(c);
}
else if (!line_input)
write(1, "\n", 1);
{
write(1, "exit\n", 5);
exit(0);
}
}
}
void test_signal(t_all *c)
// WIP HUGO
void close_fd(t_cmd *cmd)
{
if (cmd->fd_in != 0)
close(cmd->fd_in);
if (cmd->fd_out != 1)
close(cmd->fd_out);
}
// WIP HUGO
void execute_cmd(char **envp, t_cmd **cmd_arr, t_all *c)
{
pid_t pid;
pid_t wpid;
int wstatus;
int i;
int argc;
// put signal handling for SIGINT to ignore so parent process will not activate signal_handling_executiv while childs are in process
c->signal_behaviour.sa_handler = SIG_IGN;
sigaction(SIGINT, &c->signal_behaviour, NULL);
i = 0;
while(cmd_arr[i])
{
pid = fork();
if (pid == 0)
{
// activate singal handling for execution mode
c->signal_behaviour.sa_handler = sigint_handler_execution;
sigaction(SIGINT, &c->signal_behaviour, NULL);
if (cmd_arr[i]->fd_in != 0)
dup2(cmd_arr[i]->fd_in, STDIN_FILENO);
if (cmd_arr[i]->fd_out != 1)
dup2(cmd_arr[i]->fd_out, STDOUT_FILENO);
close_fd(cmd_arr[i]);
if (cmd_arr[i]->builtin_func)
{
argc = 0;
while (cmd_arr[i]->argv[argc])
argc++;
cmd_arr[i]->builtin_func(argc, cmd_arr[i]->argv, c);
exit(0);
}
else
{
write(1, "1", 1);
execve(cmd_arr[i]->argv[0], cmd_arr[i]->argv, envp);
}
}
else
close_fd(cmd_arr[i]);
i++;
}
// waitpid pour la derniere commande (pour '$?')
wpid = 1;
while (wpid > 0)
wpid = wait(&wstatus);
// to print a \n after execve was terminated by a signal
if (WIFSIGNALED(wstatus))
write(1, "\n", 1);
// put signal handling for sigint back to the signal handler for interactiv mode
c->signal_behaviour.sa_handler = sigint_handler_interactiv;
sigaction(SIGINT, &c->signal_behaviour, NULL);
}
/* void test_signal(t_all *c)
{
// TEMP
// A faire aprés être sortie du mode interactif
@@ -80,4 +144,4 @@ void test_signal(t_all *c)
sigaction(SIGQUIT, &c->signal_behaviour, NULL);
tcsetattr(STDIN_FILENO, TCSANOW, &c->interactive_termios);
}
}
} */

View File

@@ -6,79 +6,33 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/10/23 18:56:53 by lperrey #+# #+# */
/* Updated: 2021/10/30 14:28:08 by lperrey ### ########.fr */
/* Updated: 2021/11/15 20:08:26 by hulamy ### ########.fr */
/* */
/* ************************************************************************** */
#include "minishell.h"
void sigint_handler(int signum)
void sigint_handler_interactiv(int signum)
{
// Comment virer LE ^D De l'affichage ? Il ne fait pas partie de "rl_line_buffer".
if (rl_line_buffer && *rl_line_buffer)
{
return ;
}
else
{
free_exit(g_all, g_all->last_exit_status);
}
return ;
}
/* void sigquit_aka_eof_handler(int signum)
{
//ft_putstr_fd("TESTS\n", 1);
ft_putstr_fd("\n", 1);
(void)signum;
write(1, "\n", 1);
rl_replace_line("", 1);
rl_on_new_line();
rl_redisplay();
return ;
} */
int set_signals_handling(struct sigaction *ori_signal_behaviour,
struct sigaction *signal_behaviour)
{
ori_signal_behaviour->sa_handler = SIG_DFL;
/* ctrl-D exit the shell.
eof = ^D; */
signal_behaviour->sa_handler = sigint_handler;
sigaction(SIGINT, signal_behaviour, NULL);
/* ctrl-\ do nothing.
quit = ^\; */
signal_behaviour->sa_handler = SIG_IGN;
//signal_behaviour->sa_handler = sigquit_aka_eof_handler;
sigaction(SIGQUIT, signal_behaviour, NULL);
/*
** remap (^D to ^C) and (^C to ^D) in terminal
** ^D is now "SIGINT" (handle here)
** ^C is now EOF (handle in shell_loop())
*/
return (1);
}
/*
ctrl-C print a new prompt on a newline.
intr = ^C;
ctrl-D exit the shell.
eof = ^D;
ctrl-\ do nothing.
quit = ^\;
*/
void sigint_handler_execution(int signum)
{
(void)signum;
write(1, "\n", 1);
// exit(0);
}
/*
speed 38400 baud; rows 22; columns 90; line = 0;
erase = ^?; kill = ^U;
eol = M-^?; eol2 = M-^?;
swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany
imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
-flusho -extproc
*/
int set_signals_handling(struct sigaction *signal_behaviour)
{
signal_behaviour->sa_handler = sigint_handler_interactiv;
sigaction(SIGINT, signal_behaviour, NULL);
signal_behaviour->sa_handler = SIG_IGN;
sigaction(SIGQUIT, signal_behaviour, NULL);
return (1);
}

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