An open API service indexing awesome lists of open source software.

https://github.com/tigran-sargsyan-w/minishell

This project is about creating a simple shell. Yes, your own little bash. You will learn a lot about processes and file descriptors.
https://github.com/tigran-sargsyan-w/minishell

42 42school c c-language cli executor execve fork lexer mandatory minishell parser posix readline shell signals terminal unix unix-shell

Last synced: about 2 months ago
JSON representation

This project is about creating a simple shell. Yes, your own little bash. You will learn a lot about processes and file descriptors.

Awesome Lists containing this project

README

          

# Minishell 🐚✨

βœ… **Completed**: Mandatory (101/100)

![42 Logo](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXfAZMOWHDQ3DKE63A9jWhIqQaKcKqUIXvzg&s)

**Minishell** is a tiny Unix shell written in C for the 42 School curriculum.
It reproduces an essential subset of *bash* behaviour β€” command parsing, environment-variable expansion, redirections, pipelines, built-ins and proper signal handling β€” all without forking off to an external parser. The goal is to give you hands-on experience with lexical analysis, recursive-descent parsing, process control (`fork` / `execve` / `waitpid`), file-descriptor juggling and the subtleties of POSIX signals.

![Minishell](https://i.ibb.co/GL2Spnf/image.png)

---

## πŸ“š Table of Contents
- [Description](#description)
- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [How It Works](#how-it-works)
- [Tests](#tests)
- [Troubleshooting](#troubleshooting)

---

## πŸ“ Description

`minishell` launches an interactive prompt that lets you execute commands just like in your favourite terminal.
Under the hood the program first tokenises the user input, expands shell variables (`$HOME`, `$?`, …) and quotes, builds an abstract syntax tree, and finally executes it while respecting Unix semantics for pipes and redirections.
The mandatory scope follows the subject of 42 School exactly; bonus features can be toggled in the Makefile.

---

## πŸš€ Features

| πŸ—‚οΈ Category | ✨ Details |
|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Built-ins** | `echo`, `cd`, `pwd`, `export`, `unset`, `env`, `exit` |
| **Pipelines `\|`** | Unlimited number of commands connected with pipes (`ls -l \| grep .c \| wc -l`) |
| **Redirections** | `>`, `>>`, `<`, `<<` (here-doc with proper Ctrl-C cancel) |
| **Quoting Rules** | Handles single quotes, double quotes and escaped characters exactly like *bash* |
| **Environment Vars**| `$VAR` / `${VAR}` expansion, `$?` exit-status expansion |
| **Signal Handling** | Ctrl-C interrupts the current command without quitting the shell; Ctrl-\ behaves like *bash*; heredoc aborts cleanly on Ctrl-C |
| **Executable Search** | Respects `PATH`, fallback to relative/absolute paths |
| **Memory-Safe** | No leaks (checked with Valgrind 🩻), clean exit on EOF or `exit` |
| **Bonus Switches** | Toggle wildcard expansion, logical operators `&&` / `\|\|`, parentheses and more via **make bonus** (*if implemented*) |

---

## πŸ› οΈ Requirements

- **GCC / Clang** supporting C99
- **Make** utility
- **GNU Readline** (mandatory subject requirement)
- **Unix-like OS** (Linux 🐧 or macOS 🍎 tested)

---

## πŸ“¦ Installation

```
git clone https://github.com/tigran-sargsyan-w/minishell.git
cd minishell
make # builds mandatory version
# make bonus # builds bonus version (optional)
```

`libft` is included as a git subdirectory and will be built automatically.

---

## ▢️ Usage

```
./minishell
minishell$ echo "Hello, World! 🌍"
Hello, World! 🌍
minishell$ ls | grep '\.c$' > sources.txt
minishell$ cat < multi-line
> heredoc
> example
> EOF
multi-line
heredoc
example
minishell$ echo "last exit code was $?"
last exit code was 0
minishell$ exit
```

---

## πŸ” How It Works

1. **Lexer** β€” splits the input line into tokens (words, operators, quoted strings), respecting escaping rules.
2. **Parser** β€” builds a syntax tree of simple commands, I/O redirections and pipes; performs environment-variable expansion and quote removal.
3. **Executor**
* creates the required number of processes with `fork()`;
* sets up pipes and redirections (`dup2`);
* runs built-ins in the parent process when possible (`cd`, `export`, `exit`);
* waits for the last child and stores its exit status in `$?`.
4. **Signal Layer** β€” installs custom handlers for `SIGINT` and `SIGQUIT` to mimic *bash* behaviour both in the main prompt and inside heredocs.
5. **Resource Cleanup** β€” frees every allocated structure and closes all file descriptors before returning to the prompt (or exiting).

---

## πŸ—„οΈ Repository Layout

```
.
β”œβ”€β”€ Makefile
β”œβ”€β”€ include/ # public headers
β”œβ”€β”€ libft/ # custom C standard-library re-implementation
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ builtin/ # shell built-ins
β”‚ β”œβ”€β”€ env/ # env-list abstraction
β”‚ β”œβ”€β”€ executor/ # pipeline & redirection logic
β”‚ β”œβ”€β”€ lexer/ # lexical analyser
β”‚ β”œβ”€β”€ minishell_utils/ # prompt loop, signals, helpers
β”‚ β”œβ”€β”€ parser/ # AST builder and expander
β”‚ └── minishell.c # Entry point
└── tests/ # markdown specs & scripts for regression tests
```
---

## βœ… Tests

Below are organized test suites covering all core components of the project:

| 🧩 Module | πŸ”— Test Case File | |
|-------------------------|------------------|-----|
| 🧠 Lexer | [LEXER.md](tests/LEXER.md) | βœ… |
| 🧷 Parser | [PARSER.md](tests/PARSER.md) | βœ… |
| πŸ—£οΈ Quotes & Expansion | [QUOTES_AND_EXPANSION.md](tests/QUOTES_AND_EXPANSION.md) | βœ… |
| πŸ”€ Redirection | [REDIRECTION.md](tests/REDIRECTION.md) | βœ… |
| βš™οΈ Executor | [EXECUTOR.md](tests/EXECUTOR.md) | βœ… |
| 🧾 Exit Status (`$?`) | [EXIT_STATUS.md](tests/EXIT_STATUS.md) | βœ… |

---

## πŸ§ͺ Builtin Detection Script

To test **unsupported builtin commands** (i.e., those your minishell is **not required** to implement), run:

```bash
./tests/test_builtins.sh
```

This script will:
- Attempt to run various shell builtins like `source`, `bind`, `declare`, etc.
- Show the output or error for each one.
- Help confirm that your shell gracefully reports errors or ignores unsupported commands.

πŸ“Ž Location: `tests/test_builtins.sh`

---

## 🧩 Troubleshooting

| πŸ˜– Symptom | πŸ› οΈ Checklist |
|-----------|--------------|
| **Command not found / wrong binary** | Is your `$PATH` set correctly? Use `env | grep ^PATH=` inside minishell. |
| **Redirection fails with β€œBad file descriptor”** | Verify file-descriptor lifetime; ensure you close unused pipe ends. |
| **Ctrl-C kills the whole shell** | Make sure the parent process resets the default handler **after** forking. |
| **Memory leaks reported by Valgrind** | Double-check cleanup of the AST and environment list on each loop iteration. |
| **Heredoc ignores variables** | Variable expansion happens *before* heredoc delimiter matching β€” re-evaluate your lexer rules. |

---

Happy hacking β€” may your prompt never segfault! 🐚πŸ’₯