███╗░░░███╗██╗███╗░░██╗██╗░██████╗██╗░░██╗███████╗██╗░░░░░██╗░░░░░ ████╗░████║██║████╗░██║██║██╔════╝██║░░██║██╔════╝██║░░░░░██║░░░░░ ██╔████╔██║██║██╔██╗██║██║╚█████╗░███████║█████╗░░██║░░░░░██║░░░░░ ██║╚██╔╝██║██║██║╚████║██║░╚═══██╗██╔══██║██╔══╝░░██║░░░░░██║░░░░░ ██║░╚═╝░██║██║██║░╚███║██║██████╔╝██║░░██║███████╗███████╗███████╗ ╚═╝░░░░░╚═╝╚═╝╚═╝░░╚══╝╚═╝╚═════╝░╚═╝░░╚═╝╚══════╝╚══════╝╚══════╝
The subject is simply to create a minishell with some builtin commands
In order To implement a minishell first We need to parse the command and put it in a Struct so that in the executing part we can just take the commands and execute them
In the order to do this i separated the project to two parts
In the parsing part i took the input and splited it into tokens
typedef struct s_token
{
enum {
TOKEN_END,
TOKEN_WORD,
TOKEN_OLD_THAN,
TOKEN_LESS_THAN,
TOKEN_LESS_LESS,
TOKEN_GREAT_GREAT,
TOKEN_PIPE,
TOKEN_AND_AND,
TOKEN_PIPE_PIPE,
TOKEN_PARENTHESES,
} e_type;
char *value;
} t_token;
e_type: is an enum that return the index of the token assigned to it
value: is the pyload of this token
This porcess is called the lexer
The iterate over the token and put every token in the cmd struct which hold all the necessary info to execute this command
typedef struct s_cmd {
char *str;
char *path;
char *output;
char *input;
char **args;
int heredoc;
int append;
int doc[2];
int pipe;
int and;
int or;
int p[2];
int pid;
int err;
} t_cmd;
path: is the path of the command
output: hold the output file name
input: holds the input file name
args: is an two dimentional arr that holds all the arguments of this commnad including the command itslef
heredoc: 1 if i should read from the standard input and 0 if not
append: 1 if i souuld add the result of this command to the output file and 0 if not
doc: the pipe where the heredoc stores what his reading
pipe, and, or: set 1 for the variable that seprates this command and the next command and 0 in the remained tow
p: for the pipe redirection
err: 1 if an error happen during exection part
Since i have the right in only one variable i create a golbal struct where all the data is living
typedef struct s_data {
char **env;
int num_of_cmds;
t_cmd *cmds;
int index;
char *limit;
int err;
int exit_code;
int heredoc_signal;
int child_signal;
int close_heredoc;
int fd;
char *pwd;
} t_data;
env: envaroment variables
num_of_cmds: the number of commands
cmds: the struct that holds all the commands
index: the index of the current command this is used where filling the cmds struct
err: 1 if an error happen in parsing part and 0 if not
exit_code: the exit code of this command
https://youtu.be/WABO4o_y8qc
The executing part is quite simple since all the hard work has been done in the parsing part
I simply iterated over all command then i created a new child for each command with fork function
pid_t fork(void);
Then i changed the default Standartd output and Standard input with dup function
int dup2(int oldfd, int newfd);
After that i executed those commands with execve function
int execve(const char *pathname, char *const argv[], char *const envp[]);
And finaly i waited all the childs to exit
pid_t waitpid(pid_t pid, int *stat_loc, int options);
But first i checked if this command is in not builtin command cause if it's a single command and builtin command i just run it in the main porcess
run this command
git clone https://github.com/YassineEddyb/minishell && cd minishell && make && ./minishell