Minishell is a simplified Unix shell that mimics the behavior of Bash. It implements core functionalities such as command execution, pipelines, redirections, and environment variable handling. This project leverages system programming techniques and key system calls like execve()
, fork()
, pipe()
, dup2()
, and readline()
, etc...
.
Breaks user input into meaningful tokens.
Identifies commands, arguments, operators (()
, ||
, &&
, |
, >
, <
, >>
, <<
), and environment variables ($HOME
).
Example:
ls | wc -l || cat file.txt && echo "Hello world!"
This is tokenized into:
[ls] [|] [wc -l] [||] [cat file.txt] [&&] [echo "Hello world!"]
AST Tree Representation
For the command:
[ls] [|] [wc -l] [||] [cat file.txt] [&&] [echo "Hello world!"]
&&
/ \
|| echo "Hello world!"
/ \
| cat file.txt
ls wc -l
- Process Management:
fork()
,execve()
,wait()
,waitpid()
,exit()
- File & Directory Operations:
open()
,read()
,write()
,close()
,opendir()
,readdir()
,stat()
,lstat()
,unlink()
,access()
,getcwd()
,chdir()
- Redirection & Pipes:
dup()
,dup2()
,pipe()
- Signal Handling:
signal()
,sigaction()
,kill()
- Memory Management:
malloc()
,free()
- Error Handling:
strerror()
,perror()
- Environment Variables:
getenv()
-
<
- Redirect input:
Example:cat < file.txt
-
>
- Redirect output:
Example:ls > output.txt
-
>>
- Append output:
Example:ls >> output.txt
-
<<
- Here document:
Example:cat << EOF
|
- Connects the output of one command to the input of another:
Example:ls | grep minishell
-
&&
- Execute next command if the previous succeeds:
Example:ls && echo "Success"
-
||
- Execute next command if the previous fails:
Example:ls || echo "Failed"
*
- Matches any number of characters:
Example:ls *.txt
-
$
- Expands environment variables:
Example:echo $HOME
-
$?
- Expands to the last commandβs exit status:
Example:echo $?
-
$USER
- Expands to the current user:
Example:echo $USER
cd
- Change directoryecho
- Print messagesexport
- Set environment variablesunset
- Remove environment variablesenv
- Print environment variablesexit
- Terminate the shell
Manages signals like SIGINT
(Ctrl+C), SIGQUIT
(Ctrl+D), and SIGTSTP
(Ctrl+Z).
Uses system calls: signal()
, sigaction()
, kill()
minishell/
βββ builtins/ # Built-in commands
βββ execution/ # Command execution logic
βββ libft/ # Custom library functions
βββ malloc/ # Memory management logic
βββ parsing/ # Parsing logic
βββ signals/ # Signal handling logic
βββ wildcards/ # Wildcard expansion logic
βββ minishell.c # Main entry point
βββ minishell.h # Main header file
βββ Makefile # Build script
βββ README.md # Documentation
-
Clone the repository to your local machine:
git clone https://github.com/samir-ouaammou/Mini-Shell
-
Navigate to the project directory:
cd Mini-Shell/Project
-
Compile the source files using
make
:make
-
Clean up compiled files:
make clean
-
To remove all object files and the executable:
make fclean
-
To recompile the project from scratch:
make re
-
Run the program:
./minishell
β
Command Execution (Using fork(), execve(), and redirections)
β
Pipes & Redirections (Handling |, <, >, >>, <<)
β
Environment Variables (Expanding $HOME,
β
Built-in Commands (cd, echo, pwd, export, unset, env, exit)
β
Error Handling (Invalid commands, syntax errors)
β
Signal Handling (Ctrl+C, Ctrl+D)
β
Memory Management (Avoiding memory leaks)
β
() - Subshell execution
β
&& - AND Operator
β
|| - OR Operator
β
| - Pipe Operator
β
< - Input Redirection
β
> - Output Redirection
β
<< - Here Document
β
>> - Append Output Redirection
β
$ - Variable Expansion
β
$? - Last Exit Status
β
$HOME - Home Directory Expansion
β
Add Logical Operators (&&, ||)
β
Implement Command History (readline())
β
Improve Error Messages
β
Implement Job Control (fg, bg)
- Developed a custom shell with support for basic commands, pipelines, and redirections.
- Mastered the use of a lexer to tokenize input and a parser to interpret and structure commands.
- Created and managed tokens to represent individual components of commands for easier processing.
- Built an efficient abstract syntax tree (AST) to represent and execute parsed commands and operators. π³
- Used fork() and wait() to manage process execution and synchronization.
- Implemented pipe() for connecting processes and enabling inter-process communication.
- Successfully utilized exec() to execute commands and launch programs. π
- Starting the Philosophers, cub3D, and Net_Practice projects to deepen my understanding of concurrency, graphics, and networking.
- Continuing to refine my knowledge of system-level programming and dynamic memory management. π‘
- Expanding my skills in C++ to explore object-oriented programming and advanced concepts. π
- Applying the experience gained to tackle increasingly complex and challenging problems. π
The Minishell project was a fascinating journey into the heart of shell programming. It offered me a hands-on experience with process creation, command parsing, and system calls that are fundamental to building a shell. π₯οΈ The challenges of implementing pipes, redirections, and error handling pushed me to think critically about how to manage resources and memory efficiently. π‘ I worked on this project as part of a group of two students, which provided valuable experience in collaborative problem-solving and team communication. By diving deep into system-level programming, Iβve gained invaluable insights into how shells operate under the hood. Iβm eager to apply this knowledge to more advanced projects. This experience has fueled my growth as a developer, and Iβm excited to continue exploring new topics and pushing my limits. π
Thank you for checking out my minishell project! π Stay tuned for more updates as I continue to enhance my skills and tackle new challenges.